COM技术内幕--包容和聚合

包容简介:
一个包含有一个内部组件并使用了其IZ接口的外部组件的内部结构
//
COM技术内幕--包容和聚合_第1张图片

在COM中,同其他内容类似,包容也是在接口级完成的。
一个包含有一个内部组件并复用了其IY接口实现的外部组件的内部结构
///
COM技术内幕--包容和聚合_第2张图片
当外部组件聚合某个接口时,它将把接口指针直接传给客户,而并不角包容那样重新实现此接口并将函数调用转发给内部组件。
//
COM技术内幕--包容和聚合_第3张图片
聚合简介:
聚合是包容的一个特例。当一个外部组件聚合了某个内部组件的一个接口时,它并没有像包容那样重新实现此接口并明确地将调用请求转发给内部组件。
相反,外部组件将直接把内部组件的接口指针返回给客户。使用此种方法,外部组件将无需重新实现并转发接口中的所有函数。

包容和聚合的比较:
对于聚合的每一个接口,可能会包容成百上千的其他接口。这是因为当组件作为客户去使用其他组件的接口时,实际就可以看成是一种包容。
聚合则更为特殊。当某个组件已经实现了我们待实现的某个接口时,就可以使用聚合,即将此组件的接口指针传给客户。

包容的实现:

class CA:public IX,public IY
{
public:
virtual HRESULT __stdcall QueryInterface(const IID&iid,void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
// Interface IX
virtual void __stdcall Fx(){cout<<"Fx"<
// Interface IY
virtual void __stdcall Fy(){m_pIY->Fy();}
// Constructor
CA();
// Destructor
~CA();
HRESULT Init();
private:
long m_cRef;
IY* m_pIY;
};

CA::CA():m_cRef(1),m_pIY(NULL)
{
InterlockedIncrement(&g_oComponents);
}

CA::~CA()
{
InterlockedDecrement(&g_oComponents);
trace("Destroy self.");
if (m_pIY != NULL)
{
m_pIY->Release();
}
}

HRESULT CA::Init()
{
trace("Create Contained component.");
HRESULT hr = ::CoCreateInstance(CLSID_Component2,
NULL,
CLSCTX_INPROC_SERVER,
IID_IY,
(void**)&m_pIY);
if (FAILED(hr))
{
trace("Could not create contained component.");
return E_FAIL;
}
else
{
return S_OK;
}
}

// CreateInstance Fucntion
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID&iid,
void** ppv)
{
if (pUnknownOuter != NULL)
{
return CLASS_E_NOAGGREGATION;
}
CA* pA = new CA;
if (pA == NULL)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pA->Init();
if (FAILED(hr))
{
pA->Release();
return hr;
}
hr = pA->QueryInterface(iid,ppv);
pA->Release();
return hr;
}
聚合的实现:
在c++中并没有同聚合等价的特性。聚合实际上是继承性的一个动态形式,而c++的继承则总是静态的。在c++中模拟聚合的最好的方法是重载->操作符。但重载 ->操作符同COM聚合相比仍有许多限制。例如它只能将调用请求转发给某一个类,而在COM中则可以聚合任意数目的接口。


class CA:public IX
{
public:
virtual HRESULT __stdcall QueryInterface(const IID&iid,void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
// Interface IX
virtual void __stdcall Fx(){cout<<"Fx"<
// Constructor
CA();
// Destructor
~CA();
HRESULT Init();
private:
long m_cRef;
IUnknown* m_pInnerUnknown;
};

HRESULT __stdcall CA::QueryInterface(const IID&iid,
void** ppv)
{
if (iid==IID_IUnknown)
{
*ppv = static_cast(this);
}
else if (iid==IID_IX)
{
*ppv = static_cast(this);
}
else if (iid==IID_IY)
{
return m_pInnerUnknown->QueryInterface(iid,ppv)
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast(*ppv)->AddRef();
return S_OK;
}

你可能感兴趣的:(COM)