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。
Component1的类厂所做的修改,只是在类厂创建好Component1之后加上对Component1的Init()的调用,用来创建组件2。
本章代码
组件2部分:cmpnt2.cpp
cmpnt2.def
组件1部分:cmpnt1.
cmpnt1.def
组件1和组件2公用的文件
iface.h
guids.cpp
注册表文件registry.h和registry.cpp与chap07相同
运行结果
包容的主要用途
包容的主要用途是通过给已有的接口加上代码以扩展此接口。
“实现继承”,指的是继承基类代码或实现,“接口继承”,指的是继承基类类型或接口。 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技术内幕--读书笔记(7)
- com技术内幕--读书笔记(8_2)
- com技术内幕--读书笔记(2)
- COM技术内幕-读书笔记-系列之三
- 读书笔记——COM技术内幕(1)组件
- COM技术内幕-读书笔记-系列之四
- COM技术内幕-读书笔记-系列之零
- COM技术内幕-读书笔记-系列之五
- COM技术内幕-读书笔记-系列之六
- com技术内幕--读书笔记(1)
- COM技术内幕-读书笔记-系列之一
- COM技术内幕-读书笔记-系列之七
- COM技术内幕 读书笔记——第二章 接 口
- COM技术内幕-读书笔记-系列之八
- com技术内幕--读书笔记(3)
- COM技术内幕-读书笔记-系列之九
- COM技术内幕读书笔记
- com技术内幕读书笔记2
- COM技术内幕-读书笔记-系列之十
- COM技术内幕-读书笔记-系列之十一