运行时类派生
可以创建派生自另一个运行时类的运行时类,前提是基类声明为“未密封”。 类派生的 Windows 运行时术语是“可组合类”。 实现派生类的代码取决于基类是由另一个组件还是由同一组件提供。 幸运的是,你不必学习这些规则,只需从 cppwinrt.exe 编译器生成的 sources 输出文件夹中复制示例实现。
考虑以下示例:
// MyProject.idl
namespace MyProject
{
[default_interface]
runtimeclass MyButton : Windows.UI.Xaml.Controls.Button
{
MyButton();
}
unsealed runtimeclass MyBase
{
MyBase();
overridable Int32 MethodOverride();
}
[default_interface]
runtimeclass MyDerived : MyBase
{
MyDerived();
}
}
在上面的示例中,MyButton 派生自由另一个组件提供的 XAML 按钮 控件。 在这种情况下,实现类似于不可组合类的实现:
namespace winrt::MyProject::implementation
{
struct MyButton : MyButtonT<MyButton>
{
};
}
namespace winrt::MyProject::factory_implementation
{
struct MyButton : MyButtonT<MyButton, implementation::MyButton>
{
};
}
另一方面,在上面的示例中,MyDerived 派生自同一组件中的另一个类。 在这种情况下,实现需要一个额外的模板参数,用于指定基类的实现类。
namespace winrt::MyProject::implementation
{
struct MyDerived : MyDerivedT<MyDerived, implementation::MyBase>
{ // ^^^^^^^^^^^^^^^^^^^^^^
};
}
namespace winrt::MyProject::factory_implementation
{
struct MyDerived : MyDerivedT<MyDerived, implementation::MyDerived>
{
};
}
在任一情况下,实现都可以使用 base_type 类型别名限定基类中的方法:
namespace winrt::MyProject::implementation
{
struct MyButton : MyButtonT<MyButton>
{
void OnApplyTemplate()
{
// Call base class method
base_type::OnApplyTemplate();
// Do more work after the base class method is done
DoAdditionalWork();
}
};
struct MyDerived : MyDerivedT<MyDerived, implementation::MyBase>
{
int MethodOverride()
{
// Return double what the base class returns
return 2 * base_type::MethodOverride();
}
};
}
当实现类型组合另一个类时,请勿调用 as 或 try_as 来执行所组合的类的未经检查的或经检查的 QueryInterface。 请改为访问 (this->) m_inner 数据成员,并对其调用 as 或 try_as。
从一个具有非默认构造函数的类型派生
ToggleButtonAutomationPeer::ToggleButtonAutomationPeer(ToggleButton) 是非默认构造函数的一个示例 。 由于没有默认构造函数,因此,若要构造一个 ToggleButtonAutomationPeer,你需要传递 owner 。 因此,如果你从 ToggleButtonAutomationPeer 派生,则需要提供一个接受 owner 并将它传递给基类的构造函数 。 让我们来看看实际的情况。
// MySpecializedToggleButton.idl
namespace MyNamespace
{
runtimeclass MySpecializedToggleButton :
Windows.UI.Xaml.Controls.Primitives.ToggleButton
{
...
};
}
// MySpecializedToggleButtonAutomationPeer.idl
namespace MyNamespace
{
runtimeclass MySpecializedToggleButtonAutomationPeer :
Windows.UI.Xaml.Automation.Peers.ToggleButtonAutomationPeer
{
MySpecializedToggleButtonAutomationPeer(MySpecializedToggleButton owner);
};
}
// 生成的实现类型的构造函数如下所示。
// MySpecializedToggleButtonAutomationPeer.cpp
...
MySpecializedToggleButtonAutomationPeer::MySpecializedToggleButtonAutomationPeer
(MyNamespace::MySpecializedToggleButton const& owner)
{
...
}
...
唯一缺少的环节是,你需要将该构造函数参数传递给基类。 还记得我们上面提到过的 F 边界多态模式吗? 在熟悉该模式(与 C++/WinRT 使用的相同)的细节之后,你可以查明基类的名称(或者你可以查找实现类的标头文件)。 这就是在此情况下调用基类构造函数的方式。
// MySpecializedToggleButtonAutomationPeer.cpp
...
MySpecializedToggleButtonAutomationPeer::MySpecializedToggleButtonAutomationPeer
(MyNamespace::MySpecializedToggleButton const& owner) :
MySpecializedToggleButtonAutomationPeerT<MySpecializedToggleButtonAutomationPeer>(owner)
{
...
}
...
基类构造函数需要一个 ToggleButton 。 MySpecializedToggleButton 是一个 ToggleButton。
在你按照上面所述进行编辑(将构造函数参数传递给基类)之前,编译器将标记构造函数并指出:在一个名为 MySpecializedToggleButtonAutomationPeer_base<MySpecializedToggleButtonAutomationPeer> 的类型(在此情况中)上没有适当的默认构造函数 。 这实际上是实现类型的基类的基类。