前面说的都是COM的模块化,体现COM组件的封装和多态特性,而实际上COM另一大特征是在二进制级别的可重用性,包括包容和聚合。本次介绍包容,下次介绍聚合。
如下,同样借用《COM原理与应用》的图,如下:
所谓包容就是对象B在实现ISomInterface接口时,调用对象A的接口来完成这个功能。换个角度看,其实相当于对象B充当我们客户程序的角色,本来是要由B完成功能调用A来完成了,整个过程客户完全感觉不到对象A的存在,所以称作包容。
下面直接看代码实现,接着上篇博客的实现,以上文的实现的COM对象做A,本次实现新的对象B,包容对象A的IAge接口,
首先,在对象B中增加个初始化函数Init,查询得到对象A的IAge接口,如下
HRESULT CPeople::Init()
{
HRESULT hr = CoCreateInstance(CLSID_EasyComPeople, NULL, CLSCTX_INPROC_SERVER, IID_IAge, (LPVOID*)&m_pAge);
if (FAILED(hr))
{
return E_FAIL;
}
else
{
return S_OK;
}
}
然后,在对象B实现IAge接口功能的时候,调用对象A的IAge接口来完成这个功能,
//IAge
HRESULT STDMETHODCALLTYPE CPeople::PrintAge( int nAge )
{
return m_pAge->PrintAge(nAge);
}
这样便完事大吉了,包容实现就是这么简单。
前面说过了对象B相当于我们客户程序的角色,这里可以看到在对象B实现IAge的功能的时候,除了调用对象A的Iage功能,还可以在之前或之后加上很多自己的功能。
下面处理下收尾工作,
何时调用Init函数呢,答案实在工厂对象创建对象B实例的时候,如下
//IClassFactory
HRESULT STDMETHODCALLTYPE CPeopleFactory::CreateInstance( _In_ IUnknown *pUnkOuter, _In_ REFIID riid, _Out_ void **ppvObject )
{
CPeople *pObj = NULL;
HRESULT hr = S_FALSE;
*ppvObject = NULL;
//创建组件对象
pObj = new CPeople;
if (pObj == NULL)
{
return hr;
}
//初始化包容对象
hr = pObj->Init();
if (FAILED(hr))
{
delete pObj;
return hr;
}
//获得非托管第一个接口指针
hr = pObj->QueryInterface(riid, ppvObject);
if (S_OK != hr)
{
delete pObj;
}
return hr;
}
最后,在对象B销毁的时候,释放对象A的接口CPeople::~CPeople()
{
g_EasyComNumber--;//组件引用计数
if (m_pAge!=NULL)
{
m_pAge->Release();
}
}
本文完整演示代码下载链接
原创,转载请注明来自http://blog.csdn.net/wenzhou1219
来源:CSDN
作者:文大侠
链接:https://blog.csdn.net/wenzhou1219/article/details/51714157