com 有两种重要的重用模型—包容和聚合。重用是现在软件开发中很看重的一部分。重用可以大大提高开发效率。com的这两个重用模型非常的经典。包容:有两个com对象,A,B,用户只知道com对象B的存在,并不知道com对象A的存在,而com对象B知道对象A的存在,并且com对象B中的一部分功能com对象A中已经实现,com对象B有这些功能函数但是不去自己实现这部分功能,而是去调用对象A的这部分功能,当用户调用对象B的这部分功能的时候,对象B就去调用对象A的这些功能,并将结果返回给用户。聚合:则重用的更彻底,对象B根本就不去实现那部分功能,连函数都没有,用户调用对象B的那部分功能的时候,对象B直接将对象A的那部分接口暴露给用户,用户直接调用到了对象A。但是对象A受对象B的控制。
包容:
聚合:
这次只介绍包容的实现,聚合下次再介绍。
包容程序实现:
com对象A:
接口:ISomefunction.h
#ifndef __ISomefunction_H__
#define __ISomefunction_H__
#include "Unknwn.h"
extern "C" const GUID IID_ISomefunction2;
class ISomefunction : public IUnknown
{
public:
virtual void __stdcall Somefunction() = 0;
};
#endif
对象A:A.h
#ifndef __ISomefunction_H__
#include "ISomefunction.h"
//#endif
class CA : public ISomefunction
{
public:
CA();
~CA();
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
public:
virtual void __stdcall Somefunction();
private:
int m_Ref;
};
#endif
A.cpp
#include "stdafx.h"
#include <comutil.h>
#include <stdio.h>
#include "objbase.h"
#include "olectl.h"
#include "A.h"
#include "Factory.h"
#include "Registry.h"
// {D45EAF90-D34A-4F89-98AD-2084765D711B}
extern "C" const GUID CLSID_A =
{ 0xd45eaf90, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
extern "C" const GUID IID_ISomefunction2 =
{ 0xd45eaf92, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
ULONG g_LockNumber = 0;
ULONG g_ANumber = 0;
HANDLE g_hModule;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
g_hModule = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" HRESULT __stdcall DllGetClassObject(const CLSID& clsid,const IID& iid,void **ppv)
{
if(clsid == CLSID_A)
{
//CAFactory *pFactory = new CAFactory;
CAFactory *pFactory = new CAFactory;
if(pFactory == NULL) return E_OUTOFMEMORY;
HRESULT result = pFactory->QueryInterface(iid,ppv);
return result;
}
else return CLASS_E_CLASSNOTAVAILABLE;
}
extern "C" HRESULT __stdcall DllCanUnloadNow(void)
{
if((g_ANumber == 0) && (g_LockNumber == 0)) return S_OK;
else return S_FALSE;
}
extern "C" HRESULT __stdcall DllRegisterServer()
{
char szModule[1024];
DWORD dwResult = ::GetModuleFileName((HMODULE)g_hModule,szModule,1024);
if(dwResult == 0) return SELFREG_E_CLASS;
return RegisterServer(CLSID_A,szModule,"A.Object","A Component",NULL);
}
extern "C" HRESULT __stdcall DllUnregisterServer()
{
return UnregisterServer(CLSID_A,"A.Object",NULL);
}
CA::CA()
{
m_Ref = 0;
g_ANumber++;
}
CA::~CA()
{
}
HRESULT CA::QueryInterface(const IID& iid,void **ppv)
{
if(iid == IID_IUnknown)
{
*ppv = (ISomefunction *)this;
((ISomefunction *)(*ppv)) ->AddRef();
}
else if(iid == IID_ISomefunction2)
{
*ppv = (ISomefunction *)this;
((ISomefunction *)(*ppv)) ->AddRef();
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
ULONG CA::AddRef()
{
m_Ref++;
return (ULONG)m_Ref;
}
ULONG CA::Release()
{
m_Ref--;
if(m_Ref == 0)
{
g_ANumber--;
delete this;
return 0;
}
return (ULONG)m_Ref;
}
void CA::Somefunction()
{
printf("********************************\nCall function from A.\n********************************\n");
}
类厂:Factory.h
#ifndef __Factory_H__
#define __Factory_H__
#include "Unknwn.h"
class CAFactory : public IClassFactory
{
protected:
ULONG m_Ref;
public:
CAFactory();
~CAFactory();
virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
public:
virtual HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter,const IID &iid,void **ppv);
virtual HRESULT __stdcall LockServer(BOOL);
};
#endif
Factory.cpp
#include "stdafx.h"
#include "Factory.h"
#include "A.h"
extern ULONG g_LockNumber;
extern ULONG g_ANumber;
CAFactory::CAFactory()
{
m_Ref = 0;
}
CAFactory::~CAFactory()
{
}
HRESULT CAFactory::QueryInterface(const IID& iid,void **ppv)
{
if(iid == IID_IUnknown)
{
*ppv = (IUnknown *)this;
((IUnknown*)(*ppv))->AddRef();
}
else if(iid == IID_IClassFactory)
{
*ppv = (IClassFactory*)this;
((IClassFactory*)(*ppv))->AddRef();
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
ULONG CAFactory::AddRef()
{
m_Ref++;
return (ULONG)m_Ref;
}
ULONG CAFactory::Release()
{
m_Ref--;
if(m_Ref == 0)
{
delete this;
return 0;
}
return (ULONG)m_Ref;
}
HRESULT CAFactory::CreateInstance(IUnknown *pUnknownOuter,const IID& iid,void **ppv)
{
CA *pObj;
HRESULT hr;
*ppv = NULL;
hr = E_OUTOFMEMORY;
if(NULL != pUnknownOuter) return CLASS_E_NOAGGREGATION;
pObj = new CA();
if(pObj == NULL) return hr;
hr = pObj->QueryInterface(iid,ppv);
if(hr != S_OK)
{
g_ANumber--;
delete pObj;
}
return hr;
}
HRESULT CAFactory::LockServer(BOOL bLock)
{
if(bLock) g_LockNumber++;
else g_LockNumber--;
return NOERROR;
}
Registry.h Registry.cpp 和 .def文件跟之前的都是一样的,不再介绍。
com对象B
代码:
接口:ISomefunction.h
#ifndef __ISomefunction_H__
#define __ISomefunction_H__
#include "Unknwn.h"
extern "C" const GUID IID_ISomefunction;
class ISomefunction : public IUnknown
{
public:
virtual void __stdcall Somefunction() = 0;
};
#endif
IOtherfunction.h
#ifndef __IOtherfunction_H__
#define __IOtherfunction_H__
#include "Unknwn.h"
extern "C" const GUID IID_IOtherfunction;
class IOtherfunction : public IUnknown
{
public:
virtual void __stdcall Otherfunction() = 0;
};
#endif
对象B:B.h
#ifndef __ISomefunction_H__
#include "ISomefunction.h"
#endif
#ifndef __IOtherfunction_H__
#include "IOtherfunction.h"
#endif
class CB : public ISomefunction,public IOtherfunction
{
public:
CB();
~CB();
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
public:
virtual void __stdcall Somefunction();
public:
virtual void __stdcall Otherfunction();
public:
HRESULT Init();
private:
int m_Ref;
ISomefunction *m_pSomefunction;
};
B.cpp
#include "stdafx.h"
#include <comutil.h>
#include <stdio.h>
#include "objbase.h"
#include "olectl.h"
#include "B.h"
#include "Factory.h"
#include "Registry.h"
extern "C" const GUID CLSID_A =
{ 0xd45eaf90, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
extern "C" const GUID IID_ISomefunction2 =
{ 0xd45eaf92, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
extern "C" const GUID CLSID_B =
{ 0x67c51297, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
extern "C" const GUID IID_ISomefunction =
{ 0x67c51298, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
extern "C" const GUID IID_IOtherfunction =
{ 0x67c51299, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
ULONG g_LockNumber = 0;
ULONG g_BNumber = 0;
HANDLE g_hModule;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
g_hModule = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" HRESULT __stdcall DllGetClassObject(const CLSID& clsid,const IID& iid,void **ppv)
{
if(clsid == CLSID_B)
{
CBFactory *pFactory = new CBFactory;
if(pFactory == NULL) return E_OUTOFMEMORY;
HRESULT result = pFactory->QueryInterface(iid,ppv);
return result;
}
else return CLASS_E_CLASSNOTAVAILABLE;
}
extern "C" HRESULT __stdcall DllCanUnloadNow(void)
{
if((g_BNumber == 0) && (g_LockNumber == 0)) return S_OK;
else return S_FALSE;
}
extern "C" HRESULT __stdcall DllRegisterServer()
{
char szModule[1024];
DWORD dwResult = ::GetModuleFileName((HMODULE) g_hModule,szModule,1024);
if(dwResult == 0) return SELFREG_E_CLASS;
return RegisterServer(CLSID_B,szModule,"B.Object","B Component",NULL);
}
extern "C" HRESULT __stdcall DllUnregisterServer()
{
return UnregisterServer(CLSID_B,"B.Object",NULL);
}
CB::CB()
{
m_pSomefunction = NULL;
m_Ref = 0;
g_BNumber++;
}
CB::~CB()
{
if(m_pSomefunction != NULL) m_pSomefunction->Release();
}
HRESULT CB::Init()
{
HRESULT result = ::CoCreateInstance(CLSID_A,NULL,CLSCTX_INPROC_SERVER,IID_ISomefunction2,(void **)&m_pSomefunction);
if(FAILED(result)) return E_FAIL;
else return S_OK;
}
void CB::Somefunction()
{
m_pSomefunction->Somefunction();
}
void CB::Otherfunction()
{
printf("*************************************\nCall function from B.\n*************************************\n");
}
HRESULT CB::QueryInterface(const IID& iid,void **ppv)
{
if(iid == IID_IUnknown)
{
*ppv = (ISomefunction *)this;
((ISomefunction *)(*ppv))->AddRef();
}
else if(iid == IID_ISomefunction)
{
*ppv = (ISomefunction *)this;
((ISomefunction *)(*ppv))->AddRef();
}
else if(iid == IID_IOtherfunction)
{
*ppv = (IOtherfunction *)this;
((IOtherfunction *)(*ppv))->AddRef();
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
ULONG CB::AddRef()
{
m_Ref++;
return (ULONG)m_Ref;
}
ULONG CB::Release()
{
m_Ref--;
if(m_Ref == 0)
{
g_BNumber--;
delete this;
return 0;
}
return (ULONG)m_Ref;
}
类厂实现:Factory.h
#ifndef __Factory_H__
#define __Factory_H__
#include "Unknwn.h"
class CBFactory : public IClassFactory
{
protected:
ULONG m_Ref;
public:
CBFactory();
~CBFactory();
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
public:
virtual HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter,const IID &iid,void **ppv);
virtual HRESULT __stdcall LockServer(BOOL);
};
#endif
Factory.cpp
#include "stdafx.h"
#include "Factory.h"
#include "B.h"
extern ULONG g_LockNumber;
extern ULONG g_BNumber;
CBFactory::CBFactory()
{
m_Ref = 0;
}
CBFactory::~CBFactory()
{
}
HRESULT CBFactory::QueryInterface(const IID& iid,void **ppv)
{
if(iid == IID_IUnknown)
{
*ppv = (IUnknown *)this;
((IUnknown *)(*ppv)) ->AddRef();
}
else if(iid == IID_IClassFactory)
{
*ppv = (IClassFactory *)this;
((IClassFactory *)(*ppv))->AddRef();
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
ULONG CBFactory::AddRef()
{
m_Ref++;
return (ULONG)m_Ref;
}
ULONG CBFactory::Release()
{
m_Ref--;
if(m_Ref == 0)
{
delete this;
return 0;
}
return (ULONG)m_Ref;
}
HRESULT CBFactory::CreateInstance(IUnknown *pUnknownOuter,const IID& iid,void **ppv)
{
CB *pObj;
HRESULT hr;
*ppv = NULL;
hr = E_OUTOFMEMORY;
if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
pObj = new CB();
if(pObj == NULL) return hr;
pObj->Init();
hr = pObj->QueryInterface(iid,ppv);
if(hr != S_OK)
{
g_BNumber--;
delete pObj;
}
return hr;
}
HRESULT CBFactory::LockServer(BOOL bLock)
{
if(bLock) g_LockNumber++;
else g_LockNumber--;
return NOERROR;
}
解释:这里对象B中有个函数Init(),这个函数的作用是调用对象A的接口,将接口指针赋给
m_pSomefunction。对象B中的ISomefunction接口的功能是通过m_pSomefunction指针去调用对象A中的函数。
客户调用程序:
代码:IOtherfunction.h
#ifndef __IOtherfunction_H__
#define __IOtherfunction_H__
#include "Unknwn.h"
extern "C" const GUID IID_IOtherfunction;
class IOtherfunction : public IUnknown
{
public:
virtual void __stdcall Otherfunction() = 0;
};
#endif
ISomefunction.h
#ifndef __ISomefunction_H__
#define __ISomefunction_H__
#include "Unknwn.h"
extern "C" const GUID IID_ISomefunction;
class ISomefunction : public IUnknown
{
public:
virtual void __stdcall Somefunction() = 0;
};
#endif
call.cpp
#include "stdafx.h"
#include <stdio.h>
#include <comutil.h>
#include "ISomefunction.h"
#include "IOtherfunction.h"
extern "C" const GUID CLSID_B =
{ 0x67c51297, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
extern "C" const GUID IID_ISomefunction =
{ 0x67c51298, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
extern "C" const GUID IID_IOtherfunction =
{ 0x67c51299, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
/*extern "C" const GUID CLSID_B =
{0x54bf6567, 0x1007, 0x11d1, {0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
extern "C" const IID IID_Dictionary =
{ 0x54bf6568, 0x1007, 0x11d1,
{ 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ;
extern "C" const IID IID_SpellCheck =
{ 0x54bf6569, 0x1007, 0x11d1,
{ 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ;*/
int _tmain(int argc, _TCHAR* argv[])
{
IUnknown *pUnknown;
ISomefunction *pSomefunction;
IOtherfunction *pOtherfunction;
HRESULT hResult;
if(CoInitialize(NULL) != S_OK) printf("Initialize COM library failed!\n");
hResult = CoCreateInstance(CLSID_B,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(void **)&pUnknown);
if(hResult != S_OK) printf("Create object failed!\n");
hResult = pUnknown->QueryInterface(IID_ISomefunction,(void **)&pSomefunction);
if(hResult != S_OK)
{
pUnknown->Release();
printf("QueryInterface ISomefunction failed!\n");
return 0;
}
pSomefunction->Somefunction();
hResult = pSomefunction->QueryInterface(IID_IOtherfunction,(void **)&pOtherfunction);
pOtherfunction->Release();
if(hResult != S_OK)
{
pUnknown->Release();
printf("QueryInterface IOtherfunction failed!\n");
return 0;
}
pOtherfunction->Otherfunction();
pOtherfunction->Release();
CoUninitialize();
int m;
scanf("%d",&m);
return 0;
}
运行结果: