组件和接口

来源:互联网 发布:理查德施特劳斯 知乎 编辑:程序博客网 时间:2024/05/20 22:04

接口: 接口的定义#define interface struct

如下定义接口:

#include <iostream>using namespace std;#define interface structinterface IX{virtual void Fx1()=0;virtual void Fx2()=0;};interface IY{virtual void Fy1()=0;virtual void Fy2()=0;};

组件:组件是派生于接口的。

定义一个组件CA,它派生于IX和IY。

class CA:public IX,public IY{public:virtual void Fx1(){cout<<"Fx1"<<endl;}virtual void Fx2(){cout<<"Fx2"<<endl;}virtual void Fy1(){cout<<"Fy1"<<endl;}virtual void Fy2(){cout<<"Fy2"<<endl;}};
即组件和接口的关系是:接口是抽象类,用于和组件外进行通信;组件是接口的实现。

抽象类的内存结构

#include <iostream>using namespace std;class IBase{public:virtual void Fx1()=0;virtual void Fx2()=0;};class IInherit:public IBase{public:virtual void Fx2(){cout<<"Fx2"<<endl;}virtual void Fx1(){cout<<"Fx1"<<endl;};};class IOther{public:virtual void FxEx2()     //注意两个函数都必须是virtual,virtural函数会有vTable,因此实际上类的内存{                        //第一个地址处是指向vTable中FxEx2()的函数指针,抽象函数的名字是不重要的,cout<<"FxEx2"<<endl;   //因此,FxEx2()和FxEx1()两个函数的顺序是很重要的,因为顺序直接影响}                        //访问两个。virtual void FxEx1(){cout<<"FxEx1"<<endl;}};int main(){IBase *pBase=new IInherit();pBase->Fx1();pBase->Fx2();pBase=(IBase*)(new IOther);pBase->Fx1();pBase->Fx2();return 0;}
在IBase中定义的一种内存结构,就是该内存的第一个地址处是函数Fx1(),第二个内存地址处是函数Fx2(),要说明的是抽象类不能导致编译器为其分配内存空间,只是定义了一种内存分配的结构类型,在实例化该抽象类的子类实例化时才分配这样的内存结构。抽象类中的函数名只不过就是一种内存占位符而已,在编译过程中,在此内存占位符的位置用执行该vTable的指针代替。

可以看到红色部分,成功的调用不是自己子类的实例函数,原因就是抽象类定义的只是一种内存结构,与函数名无关,如果两个不同的类但具有相同的内存结构,就可以用一个抽象类函数调用另外一个完全不相关的对象的实例函数。

COM接口中所说的内存结构所包含的深层意义也就在于此,COM接口只是定义了内存结构,通过这样的内存结构就可以保证客户只用接口中定义的函数来调用组件中的函数实现,即使组件用了和接口不同的函数名,只要组件完全遵从接口的定义,就不会出问题。

http://blog.csdn.net/haoel/article/details/1948051/  虚函数表解析

C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。

虚函数表:

   C++中的虚函数是通过一张虚函数表来实现的,在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证能真实反映实际的函数。这样,在有虚函数的类的实例中,这个表被分配在了这个实例的内存中,所以当我们用父类的指针来操作一个子类的时候,这张表就显得尤为重要,就像一个地图一样,指明了实际所应该调用的函数。

   C++编译器保证虚函数表的指针存在于对象实例中最前面的位置【即不管类的第一个函数是否是虚函数,在对象的内存中,第一个地址是指向虚函数表的指针】

虚函数表的特点:

1)虚函数按照其声明顺序放于表中。

2)父类的虚函数在子类的虚函数前面。

COM在多重继承实现接口的时候,不允许是虚拟继承,因为这样会破坏COM的内存定义规范。即,COM允许在子类中有同一个父类的多个拷贝,而且必须是这样。多重继承下,如果在子类中只有父类的一份拷贝,会破坏父类的内存结构,这是不符合COM的内存规范的。