一个模拟的COM示例程序

我认为这是《Visual c++技术内幕》这本书中讲的最为出色的一个示例,将COM的“面向接口”的思路讲述得相当清晰,再加上嵌套类和引用计数的使用,让COM初学者能一窥其实质。

就我的理解,COM就好比是一瓶“胶水“,把客户exe同所需要的DLL或者其他exe”黏合“起来,而这些工作对客户来说是透明的,客户只是按双方协商好的协议,使用特定的接口就行了,只要接口保持不变,客户就不需要跟随DLL等的变化而变化,是为”面向接口“,这一切都是COM的功劳,而且COM使用包容和集合来代替继承,更加符合面向对象的思想。

// client.cpp pseudo-OLE command-line application

ContractedBlock.gif ExpandedBlockStart.gif Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->#include<stdio.h>
#include
<stddef.h>//foroffsetofinMETHOD_PROLOGUE
#include<assert.h>
#include
"interface.h"

//----------mainprogram-----------------------------------------------
intmain()//simulatesOLEclientprogram
{
TRACE(
"6Enteringclientmain/n");//第6步
IUnknown*pUnk;//Ifyoudeclarethesevoid*,youlosetype-safety
IMotion*pMot;
IVisual
*pVis;
IClassFactory
*pClf;
GetClassObject(CLSID_CSpaceship,IID_IClassFactory,(
void**)&pClf);
pClf
->CreateInstance(IID_IUnknown,(void**)&pUnk);
pUnk
->QueryInterface(IID_IMotion,(void**)&pMot);//Allthreepointersshouldwork
pMot->QueryInterface(IID_IVisual,(void**)&pVis);//
TRACE("23main:pUnk=%p,pMot=%p,pDis=%p/n",pUnk,pMot,pVis);//第23步
//Testalltheinterfacevirtualfunctions
pMot->Fly();
intnPos=pMot->GetPosition();
TRACE(
"32nPos=%d/n",nPos);//第32步
pVis->Display();
pClf
->Release();
pUnk
->Release();
pMot
->Release();
pVis
->Release();
return0;
}

// interface.h

definitions that make our code look like MFC code

ContractedBlock.gif ExpandedBlockStart.gif Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->#defineBOOLint
#defineDWORDunsignedint
#defineTRUE1
#defineFALSE0
#defineTRACEprintf
#defineASSERTassert
//----------definitionsandmacros-----------------------------------
#defineCLSID_CSpaceship10
#defineIID_IUnknown0
#defineIID_IClassFactory1
#defineIID_IMotion2
#defineIID_IVisual3
//thismacrofor16-bitWindowsonly
#defineMETHOD_PROLOGUE(theClass,localClass)/
theClass
*pThis=((theClass*)((char*)(this)-/
offsetof(theClass,m_x##localClass)));/

BOOLGetClassObject(
intnClsid,intnIid,void**ppvObj);

//----------interfacedeclarations-----------------------------------
structIUnknown
{
IUnknown()
{
TRACE(
"21013EnteringIUnknownctor%p/n",this);//第2步//第10步//第13步
}
virtualBOOLQueryInterface(intnIid,void**ppvObj)=0;
virtualDWORDRelease()=0;
virtualDWORDAddRef()=0;
};
structIClassFactory:publicIUnknown
{
IClassFactory()
{
TRACE(
"3EnteringIClassFactoryctor%p/n",this);//第3步
}
virtualBOOLCreateInstance(intnIid,void**ppvObj)=0;
};

structIMotion:publicIUnknown
{
IMotion()
{
TRACE(
"11EnteringIMotionctor%p/n",this);//第11步
}
virtualvoidFly()=0;//pure
virtualint&GetPosition()=0;
};
structIVisual:publicIUnknown
{
IVisual()
{
TRACE(
"14EnteringIVisualctor%p/n",this);//第14步
}
virtualvoidDisplay()=0;
};
classCSimulatedCmdTarget//'simulated'CSimulatedCmdTarget
{
public:
DWORDm_dwRef;
protected:
CSimulatedCmdTarget()
{
TRACE(
"19EnteringCSimulatedCmdTargetctor%p/n",this);//第1步//第9步
m_dwRef=1;//impliedfirstAddRef
}
virtual~CSimulatedCmdTarget()
{
TRACE(
"4749EnteringCSimulatedCmdTargetdtor%p/n",this);//第47步//第49步
}

DWORDExternalRelease()
{
//第18步//第38步//第40步//第42步//第44步
TRACE("1838404244EnteringCSimulatedCmdTarget::ExternalRelease--RefCount=%ld/n",m_dwRef);
if(m_dwRef==0)
return0;
if(--m_dwRef==0L)
{
TRACE(
"45deleting/n");//第45步
deletethis;
return0;
}
returnm_dwRef;
}
DWORDExternalAddRef()
{
return++m_dwRef;
}
};

// Spaceship.h

ContractedBlock.gif ExpandedBlockStart.gif Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->classCSpaceship;
//----------classdeclarations-----------------------------------------------
classCSpaceshipFactory:publicCSimulatedCmdTarget
{
public:
CSpaceshipFactory()
{
TRACE(
"5EnteringCSpaceshipFactoryctor%p/n",this);//第5步
}
~CSpaceshipFactory()
{
TRACE(
"48EnteringCSpaceshipFactorydtor%p/n",this);//第48步
}
BOOLExternalQueryInterface(
intlRid,void**ppvObj);
classXClassFactory:publicIClassFactory
{
public:
XClassFactory()
{
TRACE(
"4EnteringXClassFactoryctor%p/n",this);//第4步
}
virtualBOOLQueryInterface(intlRid,void**ppvObj);
virtualDWORDRelease();
virtualDWORDAddRef();
virtualBOOLCreateInstance(intlRid,void**ppvObj);
}m_xClassFactory;
friend
classXClassFactory;
};
classCSpaceship:publicCSimulatedCmdTarget
{
private:
intm_nPosition;//Wecanaccessthesefromalltheinterfaces
intm_nAcceleration;
intm_nColor;
public:
CSpaceship()
{
TRACE(
"16EnteringCSpaceshipctor%p/n",this);//第16步
m_nPosition=100;
m_nAcceleration
=101;
m_nColor
=102;
}
~CSpaceship()
{
TRACE(
"46EnteringCSpaceshipdtor%p/n",this);//第46步
}
BOOLExternalQueryInterface(
intlRid,void**ppvObj);
classXMotion:publicIMotion
{
public:
XMotion()
{
TRACE(
"12EnteringXMotionctor%p/n",this);//第12步
}
virtualBOOLQueryInterface(intlRid,void**ppvObj);
virtualDWORDRelease();
virtualDWORDAddRef();
virtualvoidFly();
virtualint&GetPosition();
}m_xMotion;
classXVisual:publicIVisual
{
public:
XVisual()
{
TRACE(
"15EnteringXVisualctor/n");//第15步
}
virtualBOOLQueryInterface(intlRid,void**ppvObj);
virtualDWORDRelease();
virtualDWORDAddRef();
virtualvoidDisplay();
}m_xVisual;
friend
classXVisual;//Thesemustbeatthebottom!
friendclassXMotion;
friend
classCSpaceshipFactory::XClassFactory;
};

// Spaceship.cpp pseudo-OLE command-line application

ContractedBlock.gif ExpandedBlockStart.gif Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->#include<stdio.h>
#include
<stddef.h>//foroffsetofinMETHOD_PROLOGUE
#include<ASSERT.h>
#include
"Interface.h"
#include
"Spaceship.h"
CSpaceshipFactoryg_factory;
//----------memberfunctions-----------------------------------------
BOOLCSpaceshipFactory::ExternalQueryInterface(intnIid,void**ppvObj)
{
TRACE(
"7EnteringCSpaceshipFactory::ExternalQueryInterface--nIid=%d/n",nIid);//第7步
switch(nIid)
{
caseIID_IUnknown:
caseIID_IClassFactory:
*ppvObj=&m_xClassFactory;
break;
default:
*ppvObj=NULL;
returnFALSE;
}
ExternalAddRef();
returnTRUE;
}
BOOLCSpaceshipFactory::XClassFactory::QueryInterface(
intnIid,void**ppvObj)
{
TRACE(
"EnteringCSpaceshipFactory::XClassFactory::QueryInterface--nIid=%d/n",nIid);
METHOD_PROLOGUE(CSpaceshipFactory,ClassFactory)
//makespThis
returnpThis->ExternalQueryInterface(nIid,ppvObj);//delegatetoCSpaceshipFactory
}
BOOLCSpaceshipFactory::XClassFactory::CreateInstance(
intnIid,void**ppvObj)
{
TRACE(
"8EnteringCSpaceshipFactory::XClassFactory::CreateInstance/n");//第8步
METHOD_PROLOGUE(CSpaceshipFactory,ClassFactory)//makespThis
CSpaceship*pObj=newCSpaceship();
if(pObj->ExternalQueryInterface(nIid,ppvObj))
{
pObj
->ExternalRelease();//balancereferencecount
returnTRUE;
}
returnFALSE;
}
DWORDCSpaceshipFactory::XClassFactory::Release()
{
TRACE(
"37EnteringCSpaceshipFactory::XClassFactory::Release/n");//第37步
METHOD_PROLOGUE(CSpaceshipFactory,ClassFactory)//makespThis
returnpThis->ExternalRelease();//delegatetoCSimulatedCmdTarget
}
DWORDCSpaceshipFactory::XClassFactory::AddRef()
{
TRACE(
"EnteringCSpaceshipFactory::XClassFactory::AddRef/n");
METHOD_PROLOGUE(CSpaceshipFactory,ClassFactory)
//makespThis
returnpThis->ExternalAddRef();//delegatetoCSimulatedCmdTarget
}
BOOLCSpaceship::ExternalQueryInterface(
intnIid,void**ppvObj)
{
TRACE(
"172022EnteringCSpaceship::ExternalQueryInterface--nIid=%d/n",nIid);//第17步//第20步//第22步
switch(nIid)
{
caseIID_IUnknown:
caseIID_IMotion:
*ppvObj=&m_xMotion;//BothIMotionandIVisualarederived
break;//fromIUnknown,soeitherpointerwilldo
caseIID_IVisual:
*ppvObj=&m_xVisual;
break;
default:
*ppvObj=NULL;
returnFALSE;
}
ExternalAddRef();
returnTRUE;
}
BOOLCSpaceship::XMotion::QueryInterface(
intnIid,void**ppvObj){
TRACE(
"1921EnteringCSpaceship::XMotion::QueryInterface--nIid=%d/n",nIid);//第19步//第21步
METHOD_PROLOGUE(CSpaceship,Motion)//makespThis
returnpThis->ExternalQueryInterface(nIid,ppvObj);//delegatetoCSpaceship
}
DWORDCSpaceship::XMotion::Release(){
TRACE(
"3941EnteringCSpaceship::XMotion::Release/n");//第39步//第41步
METHOD_PROLOGUE(CSpaceship,Motion)//makespThis
returnpThis->ExternalRelease();//delegatetoCSimulatedCmdTarget
}
DWORDCSpaceship::XMotion::AddRef(){
TRACE(
"EnteringCSpaceship::XMotion::AddRef/n");
METHOD_PROLOGUE(CSpaceship,Motion)
//makespThis
returnpThis->ExternalAddRef();//delegatetoCSimulatedCmdTarget
}
voidCSpaceship::XMotion::Fly(){
TRACE(
"24EnteringCSpaceship::XMotion::Fly/n");//第24步
METHOD_PROLOGUE(CSpaceship,Motion)//makespThis
TRACE("25this=%p,pThis=%p/n",this,pThis);//第25步
TRACE("26m_nPosition=%d/n",pThis->m_nPosition);//第26步
TRACE("27m_nAcceleration=%d/n",pThis->m_nAcceleration);//第27步
}
int&CSpaceship::XMotion::GetPosition(){
TRACE(
"28EnteringCSpaceship::XMotion::GetPosition/n");//第28步
METHOD_PROLOGUE(CSpaceship,Motion)//makespThis
TRACE("29this=%p,pThis=%p/n",this,pThis);//第29步
TRACE("30m_nPosition=%d/n",pThis->m_nPosition);//第30步
TRACE("31m_nAcceleration=%d/n",pThis->m_nAcceleration);//第31步
returnpThis->m_nPosition;
}
BOOLCSpaceship::XVisual::QueryInterface(
intnIid,void**ppvObj){
TRACE(
"EnteringCSpaceship::XVisual::QueryInterface--nIid=%d/n",nIid);
METHOD_PROLOGUE(CSpaceship,Visual)
//makespThis
returnpThis->ExternalQueryInterface(nIid,ppvObj);//delegateto
//CSpaceship
}
DWORDCSpaceship::XVisual::Release(){
TRACE(
"43EnteringCSpaceship::XVisual::Release/n");//第43步
METHOD_PROLOGUE(CSpaceship,Visual)//makespThis
returnpThis->ExternalRelease();//delegatetoCSimulatedCmdTarget
}
DWORDCSpaceship::XVisual::AddRef(){
TRACE(
"EnteringCSpaceship::XVisual::AddRef/n");
METHOD_PROLOGUE(CSpaceship,Visual)
//makespThis
returnpThis->ExternalAddRef();//delegatetoCSimulatedCmdTarget
}
voidCSpaceship::XVisual::Display(){
TRACE(
"33EnteringCSpaceship::XVisual::Display/n");//第33步
METHOD_PROLOGUE(CSpaceship,Visual)//makespThis
TRACE("34this=%p,pThis=%p/n",this,pThis);//第34步
TRACE("35m_nPosition=%d/n",pThis->m_nPosition);//第35步
TRACE("36m_nColor=%d/n",pThis->m_nColor);//第36步
}
//----------simulatesCOMcomponent----------------------------------
//InrealCOM,thiswouldbeDllGetClassObject,whichwouldbecalled
//wheneveraclientcalledCoGetClassObject
BOOLGetClassObject(intnClsid,intnIid,void**ppvObj)
{
ASSERT(nClsid
==CLSID_CSpaceship);
ASSERT((nIid
==IID_IUnknown)||(nIid==IID_IClassFactory));
returng_factory.ExternalQueryInterface(nIid,ppvObj);
//refcountis2,whichpreventsaccidentaldeletion
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值