用ATL建立轻量级的COM对象(2)
2006-07-21 11:44:36 来源:WEB开发网许多开发人员将智能指针看成是对过于的复杂编程任务的简化。我最初也是这么认为的。但只要留意它们使用COM智能指针的方法。就会逐渐认识到它们引入的潜在危险与它们解决的问题一样多。
关于这一点,我用一个现成的使用原始指针的函数为例:
void f(void) {
将它自然而然转换到使用CComPtr。
IFoo *pFoo = 0;
HRESULT hr = GetSomeObject(&pFoo);
if (SUCCEEDED(hr)) {
UseSomeObject(pFoo);
pFoo->Release();
}
}
void f(void) {
注意CComPtr 和 CComQIPtr输出所有受控接口成员,包括AddRef和Release。可惜当客户端通过操作符->的结果调用Release时,智能指针很健忘 ,会二次调用构造函数中的Release。显然这是错误的,编译器和链接器也欣然接受了这个代码。如果你运气好的话,调试器会很快捕获到这个错误。
CComPtr<IFoo> pFoo = 0;
HRESULT hr = GetSomeObject(&pFoo);
if (SUCCEEDED(hr)) {
UseSomeObject(pFoo);
pFoo->Release();
}
}
使用ATL智能指针的另一个要引起注意的风险是类型强制转换操作符对原始指针提供的访问。如果隐式强制转换操作符的使用存在争议。当 ANSI/ISO C++ 委员会在决定采用某个C++串类时,他们明确禁止隐式类型转换。而是要求必须显式使用c_str函数在需要常量char *(const char *)的地方传递标准C++串。ATL提供了一种隐含式的类型转换操作符顺利地解决了这个问题。通常,这个转换操作符可以根据你的喜好来使用,允许你将智能指针传递到需要用原始指针的函数。
void f(IUnknown *pUnk) {
这段代码能正确运行,但是下面的代码也不会产生警告信息,编译正常通过:
CComPtr unk = pUnk;
// 隐式调用操作符IUnknown *()
CoLockObjectExternal(unk, TRUE, TRUE);
}HRESULT CFoo::Clone(IUnknown **ppUnk) {
在这种情况下,智能指针(unk)对原始值针**ppUnk的赋值触发了与前面代码段相同的强制类型转换。在第一个例子中,不需要用AddRef。在第二个例子中,必须要用AddRef。
CComPtr unk;
CoCreateInstance(CLSID_Foo, 0, CLSCTX_ALL,
IID_IUnknown, (void **) &unk);
// 隐式调用操作符IUnknown *()
*ppUnk = unk;
return S_OK;
}
有关使用智能指针的更详细一般信息,请参见Scott Meyer的《More Effective C++》(Addison-Wesley, 1995年出版)。国内目前还没有这本书的中译本或影印本。有关COM智能指针的更多特定信息,请参见Don Box的一篇关于智能指针的专题文章http://www.develop.com/dbox/cxx/SmartPointer.htm。 (待续)
- ››建立唯美图片特效,十个jQuery插件分享
- ››建立自己的TextView和ImageView的组合View类
- ››轻量级数据交换格式 JSON轻松入门
- ››建立虚拟专用网 使用SSH保护网络通信
- ››轻量级系统 Lubuntu 10.04 发布
- ››建立一个 Derby 日历,第 3 部分: 使用事务和锁定...
- ››建立一个 Derby 日历,第 3 部分: 使用事务和锁定...
- ››建立一个 Derby 日历,第 1 部分: 理解 JDBC
- ››建立一个 Derby 日历,第 2 部分: 嵌入选项(上)...
- ››建立一个 Derby 日历,第 2 部分: 嵌入选项(下)...
- ››建立 qt for symbian 的开发环境
- ››建立一个 Android 项目的实例
更多精彩
赞助商链接