5.COM可重用性——包容

回眸只為那壹抹淺笑 提交于 2019-12-07 10:04:18

前面说的都是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


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!