C++/CX 中的继承与 C++ 中的继承不同。这是因为 C++/CX 的 ref 类实际上是 COM 对象,它通过各种聚合来实现继承。
我正在使用的示例是
public ref class MyTextBox : public TextBox {
MyTextBox() {};
~MyTextBox() {};
virtual void OnKeyDown(KeyEventArgs^ e) override {
TextBox::OnKeyDown(e);
};
};
这不起作用,因为 TextBox::OnKeyDown() 将有效地调用 MyTextBox::OnKeyDown()。这是因为虚拟方法是如何在 C++/CX 和 COM 中实现的,可以在此处阅读深入的概述。
Visual Studio 11 开发者预览解决方案
简短的版本是 OnKeyDown() 方法是 IControlOverrides 接口的一部分,由 MyTextBox 和 TextBox 实现,这要归功于一些聪明的编译器技巧。为了获得 TextBox 实现的接口指针,我们首先需要向 TextBox 询问它——如果我们询问 MyTextBox,我们将在我们开始的地方结束。因为这是 COM 中的继承,而不是 C++,所以我们通过指向基类对象的指针而不是this来做到这一点:
virtual void OnKeyDown(KeyEventArgs^ e) override {
struct IControlOverrides^ ico;
HRESULT hr = __cli_baseclass->__cli_QueryInterface(const_cast<class Platform::Guid%>(reinterpret_cast<const class Platform::Guid%>(__uuidof(struct IControlOverrides^))),reinterpret_cast<void**>(&ico));
if (!hr) {
hr = ico->__cli_OnKeyDown(e);
};
};
Visual Studio 11 测试版解决方案
与许多其他事情一样,这在 VS 11 Beta 中得到了改进。虽然 "__super::" 仍然不起作用,但它现在可以正常工作,只是为了显式调用定义它的接口:
virtual void OnKeyDown(KeyEventArgs^ e) override {
IControlOverrides::OnKeyDown(e);
};
VS 中的对象浏览器将显示 OnKeyDown() 方法在 (IControlOverrides) 中定义的接口。
问题解决了!