您所在的位置: 首页 > 读书频道 > 设计开发 > C++ >

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

http://book.51cto.com  2008-06-13 11:55  郭克新编著  电子工业出版社  我要评论(0)
  • 摘要:《Visual C++代码参考与技巧大全》第12章主要讲的是COM组件技术操作技巧,COM是开发组件的一种方法,组件是一些小的二进制程序,它可以为操作系统或者应用程序提供服务。COM技术的发展进一步加强了程序的模块化编程的思想,使应用程序在更容易扩展与升级,具有更好的灵活性和动态性,COM支持了分部使应用程序的开发,本节为大家介绍使用智能指针创建COM对象。
  • 标签:Visual C++  代码  DLL操作  COM对象  Visual C++代码参考与技巧大全

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】

回书目   上一节   下一节
让你的代码“炫”起来——WPF开发教程
Perl实例精解(第4版)
SQL Server 2005 Integration Services专家教程
WPF高级编程
CSS、DHTML和Ajax快速上手
 
 验证码: (点击刷新验证码)   匿名发表
  • 网络工程师考试案例动手实验营

  • 作者:郭春柱
  • 本书依据2009年版《网络工程师考试大纲》的考核要求,深入研究了历年网络工程师考试试题的命题风格和试题结构,对考查的知识点..
Copyright©2005-2008 51CTO.COM 版权所有