龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

C++ COM编程之接口背后的虚函数表(2)

时间:2014-10-02 11:08来源:网络整理 作者:网络 点击:
分享到:
从上图中就可以看到,初始化完成以后,指向虚函数表的__vfptr指针中的元素都被赋予了正确的虚函数值,分别指向了在类中定义的三个虚函数。也看到了

从上图中就可以看到,初始化完成以后,指向虚函数表的__vfptr指针中的元素都被赋予了正确的虚函数值,分别指向了在类中定义的三个虚函数。也看到了,__vfptr指针定义的位置也比m_iVar和m_fVar变量的位置靠前;在C++编译器中,它保证虚函数表的指针存在于对象实例中最前面的位置,这主要是为了在多层继承或是多重继承的情况下,能以高性能取到这张虚函数表,然后进行遍历,查找对应的虚函数指针,进行对应的调用。

我们都知道,虚函数是用来支持C++中的多态的,而单独的一个类,有了虚函数,而没有任何继承关系,也就是说没有子类去覆盖父类的虚函数,这样是毫无意义的。所以下面就要从各个方面进行详细的说明虚函数表。

没有实现多态的单继承

比如有如下的继承关系:

在这个继承关系中,CIF2作为CIF1的子类,但是CIF2没有重写CIF1类的任何虚函数;定义CIF2 if2Obj;实例,在派生类的实例中,它的虚函数表应该是像下面这样的:

复制代码 代码如下:

[0]     0x011513c5 {InterfaceDemo2.exe!CIF1::IF1(void)}     void *
[1]     0x011512cb {InterfaceDemo2.exe!CIF1::IF2(void)}     void *
[2]     0x01151343 {InterfaceDemo2.exe!CIF1::IF3(void)}     void *
[3]     0x01151249 {InterfaceDemo2.exe!CIF2::IF4(void)}     void *
[4]     0x01151433 {InterfaceDemo2.exe!CIF2::IF5(void)}     void *
[5]     0x01151267 {InterfaceDemo2.exe!CIF2::IF6(void)}     void *
[6]     0x00000000     void *

可以发现,虚函数按照其声明顺序存放在表中,父类的虚函数在子类的虚函数前面。

实现多态的单继承

现在我在CIF2类中,重写CIF1类的IF1函数,它们的关系如下:

在上图中,CIF2继承了CIF1,并且在CIF2类中重写了CIF1的虚函数IF1,那我们现在看看虚函数表是什么样子的?

复制代码 代码如下:

[0]     0x00b61311 {InterfaceDemo2.exe!CIF2::IF1(void)}     void *
[1]     0x00b612c6 {InterfaceDemo2.exe!CIF1::IF2(void)}     void *
[2]     0x00b61343 {InterfaceDemo2.exe!CIF1::IF3(void)}     void *
[3]     0x00b61249 {InterfaceDemo2.exe!CIF2::IF4(void)}     void *
[4]     0x00b61433 {InterfaceDemo2.exe!CIF2::IF5(void)}     void *
[5]     0x00000000     void *

你发现了什么?虚函数表中的第一项是CIF2::IF1,而不是CIF1::IF1,这说明了当在子类中重写父类的虚函数时,新的函数的地址覆盖了父类的虚函数地址,这样就能在多态时能正确的找到需要被调用的函数;而没有被覆盖的函数还是那样的顺序在虚函数表中存储着。

没有实现多态的多继承

对于简单的,没有实现多态的多继承,比如,有下面的一个多继承关系:

在子类中没有重写任何父类的虚函数,那么它的虚函数表应该是什么样子呢?

虚函数表CIF1,如下:

复制代码 代码如下:

[0]     0x001e13d9 {InterfaceDemo2.exe!CIF1::IF1(void)}     void *
[1]     0x001e12df {InterfaceDemo2.exe!CIF1::IF2(void)}     void *
[2]     0x001e1357 {InterfaceDemo2.exe!CIF1::IF3(void)}     void *
[3]     0x001e10c8 {InterfaceDemo2.exe!CIF3::IF4(void)}     void *
[4]     0x001e1041 {InterfaceDemo2.exe!CIF3::IF5(void)}     void *
[5]     0x001e1249 {InterfaceDemo2.exe!CIF3::IF6(void)}     void *
[6]     0x00000000     void *

虚函数表CIF2,如下:

精彩图集

赞助商链接