windows C++-使用 C++/WinRT 创作 API(四)

运行时类派生

可以创建派生自另一个运行时类的运行时类,前提是基类声明为“未密封”。 类派生的 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> 的类型(在此情况中)上没有适当的默认构造函数 。 这实际上是实现类型的基类的基类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值