第二章
本章讨论了接口在COM中的作用,以及COM规范对接口的内存结构要求。
DLL的接口是它所输出的那些函数,C++类的接口则是该类的成员函数集,COM接口是一组由组件实现并提供给客户使用的函数。
在COM中,接口是一个函数指针数组(就是一个函数集合),组件是一个接口集,实现了N个接口。组件封装了接口内部实现细节,使客户可以用同样的调用方式来使用不同的组件(多态)。接口设计的好的话,将可以得到可复用性极高的结构。
我们使用C++的抽象基类的多重继承来实现COM组件,使用抽象基类,C++编译器可以生成符合COM二进制标准的接口内存结构。
抽象基类 的内存结构
IX既是一个抽象基类,也是一个COM接口,是因为其内存结构符合COM规范的要求。
根据C++的抽象基类知识可以知道,IX的内部是一个指向函数列表的指针,它的大小是4。
interface IX
{
virtual void __stdcall Fx1() = 0;
virtual void __stdcall Fx2() = 0;
};
sizeof(IX) == 4
本章给出的例子,并不是创建真正的COM组件,客户与COM组件的通信也不是这样的,只是建立COM和客户的第一步,后面几章会进行完善。
//Iface.cpp
//use cl iface,cpp
//
#include <iostream>
#include <objbase.h>
using namespace std;
void trace(const char *pMsg)
{
cout<<pMsg<<endl;
}
interface IX
{
virtual void __stdcall Fx1() = 0;
virtual void __stdcall Fx2() = 0;
};
interface IY
{
virtual void __stdcall Fy1() = 0;
virtual void __stdcall Fy2() = 0;
};
class CA:public IX, public IY
{
public:
virtual void _stdcall Fx1()
{
cout<<"CA::Fx1"<<endl;
}
virtual void __stdcall Fx2()
{
cout<<"CA::Fx2"<<endl;
}
virtual void __stdcall Fy1()
{
cout<<"CA::Fy1"<<endl;
}
virtual void __stdcall Fy2()
{
cout<<"CA::Fy2"<<endl;
}
};
int main()
{
trace("client:creat an instance of the componet");
CA *pA = new CA;
//Get Ix Pointer
IX *pIx = pA;
trace("client:use the IX interface");
pIx->Fx1();
pIx->Fx2();
//Get Iy Pointer
IY *pIy = pA;
pIy->Fy1();
pIy->Fy2();
trace("client:delete the component");
delete pA;
return 0;
}
运行结果: