设为首页 加入收藏

TOP

12.1.7 使用智能指针创建COM对象
2013-10-07 00:15:53 来源: 作者: 【 】 浏览:69
Tags:12.1.7 使用 智能 指针 创建 COM 对象

12.1.7  使用智能指针创建COM对象

1.问题阐述

利用COM的API创建COM对象,一切的处理工作都要程序员手动完成,比如接口指针最后的释放,这样如果在任务繁重的情况下,很容易出现忘记释放指针的情况,为了解决这个问题,COM能够提供一种自动释放的机制,于是引入了智能指针。

2.实现技巧

使用COM中的智能指针,使对象的创建工作更加简单化。而且它提供自动销毁生成的 COM的对象机制,使程序的精力转移到其他的方面。下面看一下ATL提供的两个智能指针—CcomPtr和CComQIPtr。

CcomPtr类实现客户端基本的COM引用计数模型,CComPtr有一个数据成员,它是一个未经过任何加工的COM接口指针。其类型被作为模板参数传递。

CComPtr<IUnknown> spUnk;
CComPtr<IFun> spFun;

默认的构造函数将这个原始指针数据成员初始化为NULL。

智能指针的参数要么是原始指针,要么是相同类型的智能参数。不论哪种情况,智能指针都调用AddRef控制引用。CComPtr的赋值操作符既可以处理原始指针,也可以处理智能指针,并且在调用新分配指针的AddRef之前自动释放保存的指针。最重要的是,CComPtr的析构函数释放保存的接口(如果非空)。

CComQIPtr对于CComPtr只增加了两个成员函数,CComQIPtr有两个模板参数:一个是被操纵的指针类型,另一个是对应于这个指针类型的GUID。例如,下列代码声明了操纵IDataObject和IPersist接口的智能指针:

 CComQIPtr<IFun, &IID_IFun> spUnk;
CCom
CComQIPtr的优点是它有重载的构造函数和赋值操作符。同类版本(例如,接收相同类型的接口)仅仅进行AddRef右边的赋值/初始化操作,这实际上就是CComPtr的功能。异类版本(接收类型不一致的接口)正确调用QueryInterface来决定是否这个对象确实支持所请求的接口:
void f(IFun* spUnk) {
CComQIPtr<IFun, &IID_IFun> p;
// 同类赋值 - AddRef''s
p = spUnk;
CComQIPtr<IDataObject, &IID_IDataObject> do;
// 异类赋值 - QueryInterface''s
do = spUnk;
}

3.实例代码

本实例的目的借助于智能指针创建COM对象,建立一个基于对话框的工程。首先初始化应用工程的COM库,在CXXXXApp的InitInstance()中添加初始化语句:

if(AfxOleInit()==FALSE)
{
AfxMessageBox("初始化环境COM库失败!");
return FALSE;
}
引入智能指针类,引入组件的CLSID、接口的ID及接口函数集:
#include "..\Object\Object.h"
#include "..\Object\Object_i.c"
#include <atlbase.h>
智能指针操作代码如下:
void CExample2Dlg::OnExeBtn() 
{
UpdateData(TRUE);
CComPtr<IUnknown>  spUnk;     //定义IUnknown的智能指针
CComPtr<IFun> spFun;      //定义IFun的智能指针
try
{
HRESULT hr = spUnk.CoCreateInstance(CLSID_Fun,NULL,
CLSCTX_INPROC_SERVER);    //启动组件
if(FAILED(hr))
{
MessageBox("组件没有注册!");
return ;
}
hr = spUnk.QueryInterface(&spFun);  //查找IFun的接口
if(FAILED(hr))
{
MessageBox("没有接口IFun");
return;
}
spFun->Add(m_add1,m_add2,&m_add3);
CComBSTR s1(m_str1);
CComBSTR s2(m_str2);
CComBSTR s3;
spFun->CatString(s1,s2,&s3);
m_str3 = convert(s3.m_str);     //将BSTR转换为CString 同上
}
catch(LPCTSTR str)
{
MessageBox(str);
}
UpdateData(FALSE); 
}
上面的代码演示了使用CcomPtr智能指针,下面的代码演示了CComQIPtr的用法:

void CExample2Dlg::OnComqiBtn() 
{
 UpdateData(TRUE);
CComPtr<IUnknown>  spUnk;     //定义IUnknown的智能指针
CComQIPtr<IFun> spFun;      //定义IFun的智能指针
try
{
HRESULT hr = spUnk.CoCreateInstance(CLSID_Fun,NULL,
CLSCTX_INPROC_SERVER);    //启动组件
if(FAILED(hr))
{
MessageBox("组件没有注册!");
return ;
}
spFun = spUnk;      //会自动调用QueryInterface查找接口
if(spFun == NULL)
{
MessageBox("没有接口!");
return;
}
spFun->Add(m_add1,m_add2,&m_add3);
CComBSTR s1(m_str1);
CComBSTR s2(m_str2);
CComBSTR s3;
spFun->CatString(s1,s2,&s3);
m_str3 = convert(s3.m_str); 
}
catch(LPCTSTR str)
{
MessageBox(str);
}
UpdateData(FALSE); 
}
【责任编辑:夏书 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇12.1.10 使用ATL创建进程外组件 下一篇12.1.2 CLSID和ProgID相互转换

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: