COM技术内幕--接口

对组件的需求:
第一:组件必须动态连接
第二:它们必须隐藏其内部实现细节。

实际上COM是使用了DLL来给组件提供动态链接的能力。

带来的好处:
1.提供了一个所有组件都应遵守的标准
2.允许使用组件的多个不同版本,而且这一点对于用户而言几乎是透明的
3.使得可以按相同的方式来处理类似的组件
4.支持对远程组件的透明链接

COM接口在C++中是用纯抽象基类实现的
一个COM组件可以提供多个接口
一个C++类可以使用多继承实现一个可以提供多个接口的组件。

#include<iostream>
#include<objbase.h>


using namespace std;

void trace1(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 CTest :public IX, public IY
{
public:
virtual void __stdcall Fx1()
{
trace1("this is Fx1 ");
}
virtual void __stdcall Fx2()
{
trace1("this is Fx2 ");
}
virtual void __stdcall Fy1()
{
trace1("this is Fy1 ");
}
virtual void __stdcall Fy2()
{
trace1("this is Fy2 ");
}
};
int main(void)
{
CTest *pTest = new CTest;
IX *pIX = pTest;
pIX->Fx1();
pIX->Fx2();

IY *pIY = pTest;
pIY->Fy1();
pIY->Fy2();

delete pTest;
cin.get();
return 0;
}
运行结果:

一个接口是一个函数集合,一个组件则是一个接口集,而一个系统则是一系列组件的集合。
对于一个支持多个接口的组件,接口函数的名字出现冲突是经常会遇到的。
此种情况下,改变某个发生冲突的函数名称即可,COM对此并不关心。因为COM接口是一个二进制标准;客户同接口的连接并不是通过 其名称或其成员函数的名称完成的,而是通过它在表示它的内存块中的位置完成的。

接口理论:
1)接口的不变性
接口不会发生任何变化。实际上这是COM接口最令人震撼之处。一旦公布了一个接口,那么它将永远保持不变。不对组件进行升级时,一般不会修改已有的接口,而是加入一些新的接口。
2)多态
多态是指的是可以按同一种方式来处理不同的对象。
接口背后:
1)虚拟函数表
__interface IX
{
virtual void __stdcall Fx1() = 0;
virtual void __stdcall Fx2() = 0;
virtual void __stdcall Fx1() = 0;
virtual void __stdcall Fx2() = 0;
};
抽象基类所定义的内存块结构示例:

2)vtbl指针及实例数据
class CA:public IX
{
public:
// Implement interface IX;
virtual void __stdcall Fx1(){cout<<"CA::Fx1"<<endl;}
virtual void __stdcall Fx2(){cout<<m_Fx2<<endl;}
virtual void __stdcall Fx3(){cout<<m_Fx3<<endl;}
virtual void __stdcall Fx4(){cout<<m_Fx4<<endl;}
CA(double d):m_Fx2(d*d),m_Fx3(d*d*d),m_Fx4(d*d*d*d)
{}
double m_Fx2;
double m_Fx3;
double m_Fx4;
};

实例数据将同vtbl一块保存
3)多重实例
int main()
{
CA* pA1= new CA(1.5);
CA* pA2= new CA(2.5);
}

同一类的多个实例将共享vtbl
4)不同的类,相同的vtbl
class CB:public IX
{
public:
// Implement interface IX;
virtual void __stdcall Fx1(){cout<<"CA::Fx1"<<endl;}
virtual void __stdcall Fx2(){cout<<"CA::Fx2"<<endl;}
virtual void __stdcall Fx3(){cout<<"CA::Fx3"<<endl;}
virtual void __stdcall Fx4(){cout<<"CA::Fx4"<<endl;}
};

void foo(IX* pIX)
{
pIX->Fx1();
pIX->Fx2();

}

INT main ()
{
CA* pA = new CA(1.5);
CB* pB = new CB;
IX* pIX = pA;
foo(pIX);
pIX = pB;
foo(pIX);
}

通过 一个共同的抽象基类来一一致的使用两个不同的类。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蚂蚁_CrkRes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值