您的位置:首页 > 其它

一个模拟的COM示例程序

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

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

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

Code
#include <stdio.h>
#include <stddef.h> // for offsetof in METHOD_PROLOGUE
#include <ASSERT.h>
#include "Interface.h"
#include "Spaceship.h"
CSpaceshipFactory g_factory;
//----------member functions-----------------------------------------
BOOL CSpaceshipFactory::ExternalQueryInterface(int nIid,void** ppvObj)
{
TRACE("7 Entering CSpaceshipFactory::ExternalQueryInterface--nIid = %d\n" ,nIid); //第7 步
switch (nIid)
{
case IID_IUnknown:
case IID_IClassFactory:
*ppvObj = &m_xClassFactory;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceshipFactory::XClassFactory::QueryInterface(int nIid,void** ppvObj)
{
TRACE("Entering CSpaceshipFactory::XClassFactory::QueryInterface--nIid = %d\n", nIid);
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to CSpaceshipFactory
}
BOOL CSpaceshipFactory::XClassFactory::CreateInstance(int nIid,void** ppvObj)
{
TRACE("8 Entering CSpaceshipFactory::XClassFactory::CreateInstance\n"); //第8 步
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
CSpaceship* pObj = new CSpaceship();
if (pObj->ExternalQueryInterface(nIid, ppvObj))
{
pObj->ExternalRelease(); // balance reference count
return TRUE;
}
return FALSE;
}
DWORD CSpaceshipFactory::XClassFactory::Release()
{
TRACE("37 Entering CSpaceshipFactory::XClassFactory::Release\n"); //第37 步
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceshipFactory::XClassFactory::AddRef()
{
TRACE("Entering CSpaceshipFactory::XClassFactory::AddRef\n");
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
BOOL CSpaceship::ExternalQueryInterface(int nIid, void** ppvObj)
{
TRACE("17 20 22 Entering CSpaceship::ExternalQueryInterface--nIid = %d\n",nIid); //第17 步//第20 步//第22 步
switch (nIid)
{
case IID_IUnknown:
case IID_IMotion:
*ppvObj = &m_xMotion; // Both IMotion and IVisual are derived
break; // from IUnknown, so either pointer will do
case IID_IVisual:
*ppvObj = &m_xVisual;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceship::XMotion::QueryInterface(int nIid, void** ppvObj) {
TRACE("19 21 Entering CSpaceship::XMotion::QueryInterface--nIid = %d\n", nIid); //第19 步//第21 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to CSpaceship
}
DWORD CSpaceship::XMotion::Release() {
TRACE("39 41 Entering CSpaceship::XMotion::Release\n"); //第39 步//第41 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XMotion::AddRef() {
TRACE("Entering CSpaceship::XMotion::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XMotion::Fly() {
TRACE("24 Entering CSpaceship::XMotion::Fly\n"); //第24 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("25 this = %p, pThis = %p\n", this, pThis); //第25 步
TRACE("26 m_nPosition = %d\n", pThis->m_nPosition); //第26 步
TRACE("27 m_nAcceleration = %d\n", pThis->m_nAcceleration);//第27 步
}
int& CSpaceship::XMotion::GetPosition() {
TRACE("28 Entering CSpaceship::XMotion::GetPosition\n"); //第28 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("29 this = %p, pThis = %p\n", this, pThis); //第29 步
TRACE("30 m_nPosition = %d\n", pThis->m_nPosition); //第30 步
TRACE("31 m_nAcceleration = %d\n", pThis->m_nAcceleration);//第31 步
return pThis->m_nPosition;
}
BOOL CSpaceship::XVisual::QueryInterface(int nIid, void** ppvObj) {
TRACE("Entering CSpaceship::XVisual::QueryInterface--nIid = %d\n", nIid);
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to
// CSpaceship
}
DWORD CSpaceship::XVisual::Release() {
TRACE("43 Entering CSpaceship::XVisual::Release\n"); //第43 步
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XVisual::AddRef() {
TRACE("Entering CSpaceship::XVisual::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XVisual::Display() {
TRACE("33 Entering CSpaceship::XVisual::Display\n"); //第33 步
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
TRACE("34 this = %p, pThis = %p\n", this, pThis); //第34 步
TRACE("35 m_nPosition = %d\n", pThis->m_nPosition); //第35 步
TRACE("36 m_nColor = %d\n", pThis->m_nColor); //第36 步
}
//----------simulates COM component ----------------------------------
// In real COM, this would be DllGetClassObject, which would be called
// whenever a client called CoGetClassObject
BOOL GetClassObject(int nClsid, int nIid, void** ppvObj)
{
ASSERT(nClsid == CLSID_CSpaceship);
ASSERT((nIid == IID_IUnknown) || (nIid == IID_IClassFactory));
return g_factory.ExternalQueryInterface(nIid, ppvObj);
// refcount is 2, which prevents accidental deletion
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: