com技术内幕--读书笔记(8_1)

第8章


“实现继承”,指的是继承基类代码或实现,“接口继承”,指的是继承基类类型或接口。 COM支持的继承是接口继承,不支持实现继承。实现继承会导致一个对象的实现同另外一个对象实现关联起来,当基类修改后,派生类也就必须被修改,甚至客户端的程序也需要修改,这显然有悖于COM组件编程的基本思想。

在C++中,对类的改造用包容和继承来实现的。在COM中,对组件的改造是使用包容和聚合来实现的,包容和聚合都是在接口级实现的。


包容

包容,是一个组件使用另外一个组件的技术,分别成为外部组件和内部组件。

包容的情况下,外部组件包含指向内部组件接口的指针,外部组件只是内部组件的一个客户。外部组件使用内部组件的接口来实现它自己的接口,并且可以在接口的实现函数加上它对内部组件接口实现的修改。

组件的包容类似c++的包容。


示意图如下



包容的实现

在下面的例子中,组件1(Component1)是一个实现了IX和IY接口的外部组件,它复用了组件2(组件1包容的内部组件)对IY接口的实现。源码与第七章的没多大差别,只是在组建1中加入了一个Init()的函数,用来创建组件2中的IY接口指针。组件2是一个典型的COM组件。当客户向Component1请求IY接口时,Component1将返回其IY接口的一个指针。当客户调用Component1中的IY接口时,Component1通过如下的代码将把这些调用请求转发给Component2。

void __stdcall CA::Fy()
{
    m_pIy->Fy();
}
当Component1将自己销毁时,它将调用m_pIy上的Release,以使Component2将自己从内存释放。

Component1的类厂所做的修改,只是在类厂创建好Component1之后加上对Component1的Init()的调用,用来创建组件2。


本章代码

组件2部分:cmpnt2.cpp

//
//cmpnt2.cpp
//use: cl /LD cmpnt2.cpp guids.cpp registry.cpp cmpnt2.def uuid.lib ole32.lib advapi32.lib    
//     regsvr32 /s cmpnt2.dll
//     ole32.lib COMLIBRARY advapi32.lib REGISTER
#include <objbase.h>
#include "iface.h"
#include "registry.h"
#include <iostream>
#include <string>
using namespace std;

//global function
//
static HMODULE g_hModule = NULL;  //COMPONENT2 MODULE HANDLE
static long g_lComponent = 0;     //COMPONENT2 COUNT
static long g_lServerLocks = 0;   //CFactory COUNT

//Friendly Name
const char g_szFriendlyName[]
   = "Inside COM, Chapter 8 Example 1, Component 2";

//Version-independent ProgID
const char g_szVerIndProgID[] = "InsideCOM.chap08.ex1.cmpnt2";

//ProgID
const char g_szProgID[] = "InsideCOM.chap08.ex1.cmpnt2.1";

//trace function
void trace(string msg)
{
	cout<<msg<<endl;
}

////////////////////////////////////////////
//class CB
//
class CB : public IY
{
public:
	virtual HRESULT __stdcall QueryInterface(const IID& iid, void **ppv);
	virtual ULONG   __stdcall AddRef();
	virtual ULONG   __stdcall Release();
	virtual void    __stdcall Fy() {cout<<"CB::Fy"<<endl;}

	CB();
	~CB();

private:
	long m_cRef;
};

CB::CB():m_cRef(1)
{
	InterlockedIncrement(&g_lComponent);
}

CB::~CB()
{
	trace("component2 destroy self");
	InterlockedDecrement(&g_lComponent);
}

ULONG __stdcall CB::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

ULONG __stdcall CB::Release()
{
	if(InterlockedDecrement(&m_cRef) == 0)
	{	
		delete this;
		return 0;
	}
	return m_cRef;
}

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

/////////////////////////////////////////////
//class factory
//
class CFactory : public IClassFactory
{
public:
	//interface iunknown
	virtual HRESULT __stdcall QueryInterface(const IID& iid, void **ppv);
	virtual ULONG   __stdcall AddRef();
	virtual ULONG   __stdcall Release();
	//interface iclassfactory
	virtual HRESULT __stdcall CreateInstance(IUnknown *pIUnknownOuter, const IID& iid, void **ppv);
	virtual HRESULT __stdcall LockServer(BOOL bLock);

	CFactory();
	~CFactory();
private:
	long m_cRef;
};

CFactory::CFactory():m_cRef(1)
{
}

CFactory::~CFactory()
{
	trace("component2 cfactory : destroy self");
}

HRESULT __stdcall CFactory::QueryInterface(const IID& iid, void **ppv)
{
	if(iid == IID_IUnknown || iid == IID_IClassFactory)
	{
		*ppv = static_cast<IClassFactory*>(this);
	}
	else
	{
		*ppv = NULL;
		return E_NOINTERFACE;
	}
	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
	return S_OK;
}

ULONG __stdcall CFactory::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

ULONG __stdcall CFactory::Release()
{
	if(InterlockedDecrement(&m_cRef) == 0)
	{
		delete this;
		return 0;
	}
	return m_cRef;
}

//CreateInstance
HRESULT __stdcall CFactory::CreateInstance(IUnknown *pIUnknownOuter, const IID& iid, void **ppv)
{
	if(pIUnknownOuter != NULL)
	{
		trace("no aggregation");
		return CLASS_E_NOAGGREGATION;
	}
	//Create Compnent2
	CB *pB = new CB();
	if(pB == NULL)
	{
		return E_OUTOFMEMORY;
	}
	//Get Request interface
	HRESULT hr = pB->QueryInterface(iid, ppv);

	//Release IUnknown interface
	pB->Release();
	return hr;
}

HRESULT __stdcall CFactory::LockServer(BOOL bLock)
{
	if(bLock == TRUE)
	{
		InterlockedIncrement(&g_lServerLocks);
	}	
	else
	{
		InterlockedDecrement(&g_lServerLocks);
	}
	return S_OK;
}

////////////////////////////////////////
//export functions
//
//Get Interface IClassFactory
STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void **ppv)
{
	if(clsid != CLSID_Component2)
		return CLASS_E_CLASSNOTAVAILABLE;

	CFactory *pFactory = new CFactory();
	if(pFactory == NULL)
	{
		return E_OUTOFMEMORY;
	}
	HRESULT hr = pFactory->QueryInterface(iid, ppv);
	pFactory->Release();
	return hr;
}

STDAPI DllCanUnloadNow()
{
	if(g_lComponent == 0 && g_lServerLocks == 0)
		return S_OK;
	else
		return S_FALSE;
}

STDAPI DllRegisterServer()
{
	return RegisterServer(g_hModule,
						  CLSID_Component2,
						  g_szFriendlyName,
						  g_szVerIndProgID,
						  g_szProgID);
}

STDAPI DllUnRegisterServer()
{
	return UnregisterServer(CLSID_Component2,
							g_szVerIndProgID,
							g_szProgID);
}

BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpvReserved)
{
	if(dwReason == DLL_PROCESS_ATTACH)
	{
		g_hModule = hModule;
	}
	return TRUE;
}

cmpnt2.def

LIBRARY      cmpnt2.dll
DESCRIPTION	 'Chapter08 Component2'
EXPORTS      DllGetClassObject    @2   private
             DllCanUnloadNow      @3     private
		     DllRegisterServer    @4   private
		     DllUnRegisterServer  @5 private

组件1部分:cmpnt1.
//
//cmpnt1.cpp
//use: cl /LD cmpnt1.cpp guids.cpp registry.cpp cmpnt2.def uuid.lib ole32.lib advapi32.lib    
//     regsvr32 /s cmpnt1.dll
//     ole32.lib COMLIBRARY advapi32.lib REGISTER
#include <objbase.h>
#include "iface.h"
#include "registry.h"
#include <iostream>
#include <string>
using namespace std;

//global function
//
static HMODULE g_hModule = NULL;  //COMPONENT1 MODULE HANDLE
static long g_lComponent = 0;     //COMPONENT1 COUNT
static long g_lServerLocks = 0;   //CFactory COUNT

//Friendly Name
const char g_szFriendlyName[]
   = "Inside COM, Chapter 8 Example 1, Component 1";

//Version-independent ProgID
const char g_szVerIndProgID[] = "InsideCOM.chap08.ex1.cmpnt1";

//ProgID
const char g_szProgID[] = "InsideCOM.chap08.ex1.cmpnt1.1";

//trace function
void trace(string msg)
{
	cout<<msg<<endl;
}

////////////////////////////////////////////
//class CA
//
class CA : public IX, public IY
{
public:
	virtual HRESULT __stdcall QueryInterface(const IID& iid, void **ppv);
	virtual ULONG   __stdcall AddRef();
	virtual ULONG   __stdcall Release();
	virtual void    __stdcall Fx() {cout<<"CA::Fx"<<endl;}
	virtual void    __stdcall Fy();

	CA();
	~CA();

	HRESULT __stdcall Init();
private:
	//pointer to the contained components's IY interface
	IY  *m_pIy;
	long m_cRef;
};

CA::CA():m_cRef(1)
{
	InterlockedIncrement(&g_lComponent);
	m_pIy = NULL;
}

CA::~CA()
{
	trace("component1 destroy self");
	InterlockedDecrement(&g_lComponent);
	if(m_pIy != NULL)
	{
		m_pIy->Release();
	}
}

ULONG __stdcall CA::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

ULONG __stdcall CA::Release()
{
	if(InterlockedDecrement(&m_cRef) == 0)
	{	
		delete this;
		return 0;
	}
	return m_cRef;
}

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

void __stdcall CA::Fy()
{
	m_pIy->Fy();
}

HRESULT __stdcall CA::Init()
{
	HRESULT hr = CoCreateInstance(CLSID_Component2, 
								  NULL,
								  CLSCTX_INPROC_SERVER,
								  IID_IY,
								  (void**)&m_pIy);
	if(FAILED(hr))
	{
		trace("couldn't create contained component");
		return E_FAIL;
	}
	else
	{
		return S_OK;
	}
}

/////////////////////////////////////////////
//class factory
//
class CFactory : public IClassFactory
{
public:
	//interface iunknown
	virtual HRESULT __stdcall QueryInterface(const IID& iid, void **ppv);
	virtual ULONG   __stdcall AddRef();
	virtual ULONG   __stdcall Release();
	//interface iclassfactory
	virtual HRESULT __stdcall CreateInstance(IUnknown *pIUnknownOuter, const IID& iid, void **ppv);
	virtual HRESULT __stdcall LockServer(BOOL bLock);

	CFactory();
	~CFactory();
private:
	long m_cRef;
};

CFactory::CFactory():m_cRef(1)
{
}

CFactory::~CFactory()
{
	trace("component1 cfactory : destroy self");
}

HRESULT __stdcall CFactory::QueryInterface(const IID& iid, void **ppv)
{
	if(iid == IID_IUnknown || iid == IID_IClassFactory)
	{
		*ppv = static_cast<IClassFactory*>(this);
	}
	else
	{
		*ppv = NULL;
		return E_NOINTERFACE;
	}
	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
	return S_OK;
}

ULONG __stdcall CFactory::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

ULONG __stdcall CFactory::Release()
{
	if(InterlockedDecrement(&m_cRef) == 0)
	{
		delete this;
		return 0;
	}
	return m_cRef;
}

//CreateInstance
HRESULT __stdcall CFactory::CreateInstance(IUnknown *pIUnknownOuter, const IID& iid, void **ppv)
{
	if(pIUnknownOuter != NULL)
	{
		trace("no aggregation");
		return CLASS_E_NOAGGREGATION;
	}
	//Create Compnent1
	CA *pA = new CA();
	if(pA == NULL)
	{
		return E_OUTOFMEMORY;
	}
	HRESULT hr = pA->Init();
	if(FAILED(hr))
	{
		//Initialize failed.Delete Component
		pA->Release();
		return hr;
	}
	//Get Request interface
	hr = pA->QueryInterface(iid, ppv);

	//Release IUnknown interface
	pA->Release();
	return hr;
}

HRESULT __stdcall CFactory::LockServer(BOOL bLock)
{
	if(bLock == TRUE)
	{
		InterlockedIncrement(&g_lServerLocks);
	}	
	else
	{
		InterlockedDecrement(&g_lServerLocks);
	}
	return S_OK;
}

////////////////////////////////////////
//export functions
//
//Get Interface IClassFactory
STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void **ppv)
{
	if(clsid != CLSID_Component1)
		return CLASS_E_CLASSNOTAVAILABLE;

	CFactory *pFactory = new CFactory();
	if(pFactory == NULL)
	{
		return E_OUTOFMEMORY;
	}
	HRESULT hr = pFactory->QueryInterface(iid, ppv);
	pFactory->Release();
	return hr;
}

STDAPI DllCanUnloadNow()
{
	if(g_lComponent == 0 && g_lServerLocks == 0)
		return S_OK;
	else
		return S_FALSE;
}

STDAPI DllRegisterServer()
{
	return RegisterServer(g_hModule,
						  CLSID_Component1,
						  g_szFriendlyName,
						  g_szVerIndProgID,
						  g_szProgID);
}

STDAPI DllUnRegisterServer()
{
	return UnregisterServer(CLSID_Component1,
							g_szVerIndProgID,
							g_szProgID);
}

BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpvReserved)
{
	if(dwReason == DLL_PROCESS_ATTACH)
	{
		g_hModule = hModule;
	}
	return TRUE;
}

cmpnt1.def
LIBRARY cmpnt1.dll
DESCRIPTION 'Chapter08 Component1'

EXPORTS DllGetClassObject   @2 private
        DllCanUnloadNow     @3 private
        DllRegisterServer   @4 private
		DllUnRegisterServer @5 private

组件1和组件2公用的文件

iface.h

#include <objbase.h>

interface IX:IUnknown
{
	virtual void __stdcall Fx() = 0;
};

interface IY:IUnknown
{
	virtual void __stdcall Fy() = 0;
};

extern const IID IID_IX;  //Interface ID for IX
extern const IID IID_IY;  //Interface ID for IY

extern const CLSID CLSID_Component1; //CLSID for Cmpnt1 
extern const CLSID CLSID_Component2; //CLSID for Cmpnt2

guids.cpp

#include <objbase.h>

// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IX = 
	{0x32bb8320, 0xb41b, 0x11cf,
	{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IY = 
	{0x32bb8321, 0xb41b, 0x11cf,
	{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

// {0c092c22-882c-11cf-a6bb-0080c7b2d682}
extern const CLSID CLSID_Component1 =
	{0x0c092c22, 0x882c, 0x11cf,
	{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

// {0c092c23-882c-11cf-a6bb-0080c7b2d682}
extern const CLSID CLSID_Component2 =
	{0x0c092c23, 0x882c, 0x11cf,
	{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;


注册表文件registry.h和registry.cpp与chap07相同

运行结果

com技术内幕--读书笔记(8_1)_第1张图片



包容的主要用途

包容的主要用途是通过给已有的接口加上代码以扩展此接口。

你可能感兴趣的:(null,读书,delete,Class,interface)