Windows Store apps开发[32]C++/CX Part 2 of [n]: hat(^)类型
注:本文由BeyondVincent(破船)原创首发
转载请注明出处:BeyondVincent(破船)@DevDiv.com
更多内容请查看下面的帖子
[DevDiv原创]Windows 8 开发Step by Step
关于本次系列的一个介绍:C++/CX Part 0 of [n]: C++/CX简介
hat(^)是C++/CX中非常明显的一个特征——当第一次看C++/CX代码时,几乎很难不注意到它的存在。那么,hat(^)究竟是什么类型呢?hat类型是这样的一个智能指针:
(1)、自动管理Windows Runtime对象的生命周期
(2)、提供自动类型转换的功能,以简化Windows Runtime对象的使用
首先,开始讨论如何通过WRL来使用Windows Runtime对象,然后解释C++/CX的hat是如何让事情变得简单。为了演示的目的,我使用如下Number类的修改版本,Number类在Part1中有介绍:
public interface struct IGetValue { int GetValue() = 0; }; public interface struct ISetValue { void SetValue(int value) = 0; }; public ref class Number sealed : public IGetValue, ISetValue { public: Number() : _value(0) { } virtual int GetValue() { return _value; } virtual void SetValue(int value) { _value = value; } private: int _value; }; 在被修改的Number类实现中,我定义了一对接口:IGetValue和ISetValue,这是声明了Number的两个成员函数;接着Number实现了这两个接口。其它的,看起来应该很熟悉。
注意:Number实际上实现了三个Windows Runtime接口:除了IGetValue和ISetValue,编译器仍然会生成__INumberPublicNonVirtuals接口,这个接口由Number实现。因为Number的所有成员都已经被显示的声明在接口中(IGetValue和ISetValue)了,所以编译器生成的__INumberPublicNonVirtuals接口没有声明任何成员。及时这样,这个接口也是必须要有的,因为它是作为Number类的缺省接口。每一个runtime对象都必须有一个缺省接口,并且缺省接口对类来说总是唯一的。稍后,我们会看到为什么缺省接口非常重要。
Windows Runtime引用类型使用引用计数来管理对象的生命周期。所有的Windows Runtime接口(包括Number实现的三个接口)都直接继承自IInspectable接口,该接口继承自COM IUnknown接口。IUnknown有三个成员方法,用于控制对象的生命周期和允许类型转换。
在MSDN上的一篇文章“引用计数管理的规则”全面的概述了IUnknown生命周期管理是如何进行的。规则非常的简单:每次创建一个新的引用对象时,必须调用IUnknown::AddRef方法来将对象的引用计数加1;每当销毁一个引用对象时,必须调用IUnknown::Release方法来将对象的引用计数减1。引用计数初始化时为0,之后会有一系列关于AddRef和Release的调用,当引用计数再次为0时,对象将被销毁。
当然在进行C++编程时,我们应该很少——几乎从来没有——去直接调用AddRef和Release方法。取而代之的是,使用智能指针,可以在需要的时候自动的进行调用。使用智能指针可以确保对象不会因为没有调用Release而泄露,或者过早调用Release而引起对象销毁,从而导致AddRef失败。
ATL包含CComPtr和一些相关的智能指针,它们已经长期用于COM编程中对象的自动管理引用计数,同样它们都实现了IUnknown。WRL包含ComPtr,该指针对CComPtr进行了改进(例如:ComPtr不需要重载运算符&,而CComPtr是需要的)。
For those who have not done much COM programming and are unfamiliar with ComPtrs: if you've used shared_ptr (included as part of C++11, C++ TR1, and Boost), ComPtr has effectively the same behavior with respect to lifetime management. The mechanism is different (ComPtr makes use of the internal reference counting provided by IUnknown, while shared_ptrsupports arbitrary types and must thus use an external reference count), but the lifetime management behavior is the same.
The C++/CX hat has exactly the same lifetime management semantics as a ComPtr. When a T^ is copied, AddRef is called to increment the reference count, and when a T^ goes out of scope or is reassigned, Release is called to decrement the reference count. We can consider a simple example to demonstrate the reference counting behavior:
类型转换
通过WRL使用对象
通过C++/CX使用对象
最后:注意事项最后:注意事项