统一构造
在 C++/WinRT 版本 2.0 及更高版本中,有一种优化的构造形式可供你使用,它被称作“统一构造”(请参见 C++/WinRT 2.0 中的新增功能和更改)。
若要使用统一构造而不是 winrt::make,你需要一个激活工厂。 要生成激活工厂,一种好的方式是向 IDL 添加构造函数。
// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{
runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
{
MainPage();
BookstoreViewModel MainViewModel{ get; };
}
}
然后,在 MainPage.h
中声明和初始化 m_mainViewModel;此操作只需一步,如下所示。
// MainPage.h
...
struct MainPage : MainPageT<MainPage>
{
...
private:
Bookstore::BookstoreViewModel m_mainViewModel;
...
};
}
...
接下来,在 MainPage.cpp 中的 MainPage 构造函数中,无需使用代码 m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();。
实例化和返回具现类型和接口
以下具现类型和实例的示例可能类似于使用的项目。 请记住,具现类型(如此示例中的一种具现类型)是工具生成的,而不是你自己创作的内容。
struct MyRuntimeClass : MyProject::IMyRuntimeClass, impl::require<MyRuntimeClass,
Windows::Foundation::IStringable, Windows::Foundation::IClosable>
// MyRuntimeClass 是具现类型;具现接口包括 IMyRuntimeClass 、IStringable 和 IClosable 。
// 本主题已展示你可用来实例化具现类型的不同方法。
// 以下是提醒和总结,这里使用 MyRuntimeClass 作为示例。
// The runtime class is implemented in another compilation unit (it's either a Windows API,
// or it's implemented in a second- or third-party component).
MyProject::MyRuntimeClass myrc1;
// The runtime class is implemented in the same compilation unit.
MyProject::MyRuntimeClass myrc2{ nullptr };
myrc2 = winrt::make<MyProject::implementation::MyRuntimeClass>();
// 你可以访问一个具现类型的所有接口的成员。
// 可以将具现类型返回到调用方。
// 具现类型和接口派生自 winrt::Windows::Foundation::IUnknown 。
// 因此,你可以对具现类型或接口调用 IUnknown::as 以查询其他也可使用或返回到调用方的具现接口。
// as 成员函数的工作方式类似于 QueryInterface 。
void f(MyProject::MyRuntimeClass const& myrc)
{
myrc.ToString();
myrc.Close();
IClosable iclosable = myrc.as<IClosable>();
iclosable.Close();
}
激活工厂
创建 C++/WinRT 对象的便利直接的方式如下所示。
using namespace winrt::Windows::Globalization::NumberFormatting;
...
CurrencyFormatter currency{ L"USD" };
// 不过,有时你可能想要自己创建激活工厂,然后在方便时从其创建对象。
// 下面的一些示例向你展示了如何使用 winrt::get_activation_factory 函数模板来实现此目的。
using namespace winrt::Windows::Globalization::NumberFormatting;
...
auto factory = winrt::get_activation_factory<CurrencyFormatter, ICurrencyFormatterFactory>();
CurrencyFormatter currency = factory.CreateCurrencyFormatterCode(L"USD");
//
using namespace winrt::Windows::Foundation;
...
auto factory = winrt::get_activation_factory<Uri, IUriRuntimeClassFactory>();
Uri uri = factory.CreateUri(L"http://www.contoso.com");
// 上面两个示例中的类是来自 Windows 命名空间的类型。
// 在接下来的示例中,ThermometerWRC::Thermometer 是在 Windows 运行时组件中实现的自定义类型。
auto factory = winrt::get_activation_factory<ThermometerWRC::Thermometer>();
ThermometerWRC::Thermometer thermometer = factory.ActivateInstance<ThermometerWRC::Thermometer>();
成员/类型多义性
当成员函数的名称与类型的名称相同时,会产生多义性。 根据 C++ 的在成员函数中进行非限定名称查找的规则,必须先搜索类,然后才能在命名空间中进行搜索。 “替换失败不是错误 (SFINAE)”规则不适用(在对函数模板进行重载解析时适用)。 因此,如果类中的名称没有意义,则编译器不会继续查找更好的匹配,它会直接报告一个错误。
struct MyPage : Page
{
void DoWork()
{
// This doesn't compile. You get the error
// "'winrt::Windows::Foundation::IUnknown::as':
// no matching overloaded function found".
auto style{ Application::Current().Resources().
Lookup(L"MyStyle").as<Style>() };
}
}
在上面的代码中,编译器认为你是在将 FrameworkElement.Style()(这在 C++/WinRT 中是成员函数)作为模板参数传递给 IUnknown::as。 解决方案是将名称 Style 强制解释为类型 Windows::UI::Xaml::Style。
struct MyPage : Page
{
void DoWork()
{
// One option is to fully-qualify it.
auto style{ Application::Current().Resources().
Lookup(L"MyStyle").as<Windows::UI::Xaml::Style>() };
// Another is to force it to be interpreted as a struct name.
auto style{ Application::Current().Resources().
Lookup(L"MyStyle").as<struct Style>() };
// If you have "using namespace Windows::UI;", then this is sufficient.
auto style{ Application::Current().Resources().
Lookup(L"MyStyle").as<Xaml::Style>() };
// Or you can force it to be resolved in the global namespace (into which
// you imported the Windows::UI::Xaml namespace when you did
// "using namespace Windows::UI::Xaml;".
auto style = Application::Current().Resources().
Lookup(L"MyStyle").as<::Style>();
}
}
非限定名称查找有一个特殊的例外,即名称后面跟有 ::,在这种情况下,它会忽略函数、变量和枚举值。 这样你就可以执行如下所示的代码。
struct MyPage : Page
{
void DoSomething()
{
Visibility(Visibility::Collapsed); // No ambiguity here (special exception).
}
}
对 Visibility() 的调用会解析为 UIElement.Visibility 成员函数名称。 但是参数 Visibility::Collapsed 在 Visibility 一词后面跟有 ::,因此系统会忽略方法名称,编译器会查找枚举类。
标签:windows,auto,factory,C++,Windows,MainPage,API,winrt,具现 From: https://blog.csdn.net/m0_72813396/article/details/140759511