您的位置:首页 > 其它

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

2012-02-05 23:09 423 查看
第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相同

运行结果



包容的主要用途

包容的主要用途是通过给已有的接口加上代码以扩展此接口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: