深刻理解C++虚函数表

  虚函数表是C++类中存放虚函数的一张表,理解虚函数表对于理解多态很重要。html

  本次使用的编译器是VS2013,为了简化操做,不用去操做函数指针,我使用到了VS的CL编译选项来查看类的内存布局。ios

  CL使用方法:函数

  (1)在开始菜单中的vs目录下打开"Visual Studio Tools"目录,找到"VS2013 开发人员命令提示",打开它;布局

  (2)将你要编译的文件放到该命令行对应的文件夹中。spa

  (3)输入cl "文件名" /d1reportSingleClassLayout"类名"命令行

  (具体的使用方法能够参考如下博客:http://www.cnblogs.com/dsky/archive/2012/02/07/2340984.html)指针

  例子:code

#include <iostream>
using namespace std;

class C {
public:    
    int a;
    int b;
};

int main() {
    return 0;
}

  输出结果:htm

 

 

  (1)单个类的虚函数表blog

class C {
public:    
    virtual void foo() {}
    int m;
};

  结果分析:能够看见虚表处于类的最开始处,这是为了提升效率和正确查找虚函数。

  (2)单继承

class Base {
public:
    virtual void v1() {}
    int b;
};

class Derived : public Base {
public:    
    virtual void v2() {}
    int d;
};

  结果分析:在类Derived的最前面是类Base,与咱们所预期的同样。虚表并非Base和Derived都有,而是只有Base有,Derived中的虚函数放在了Base里的虚表中。

 

  (3)单继承 + 覆盖

class Base {
public:
    virtual void v1() {}
    int b;
};

class Derived : public Base {
public:    
    virtual void v1() {}
    virtual void v2() {}
    int d;
};

  结果分析:咱们在Derived中覆盖了Base的v1,从结果能够看出虚表中原来的Base::v1变为了Derived::v1

 

  (4)多继承

class Base1 {
public:
    virtual void v1() {}
    int b1;
};

class Base2 {
public:    
    virtual void v2() {}
    int b2;
};

class Derived : public Base1, public Base2 {
public:    
    virtual void v3() {}
    int d;
};

  结果分析:两个基类各自有本身的虚表,而Derived的虚函数放在了第一张虚表中。

 

  (5)虚继承

class VBase {
public:
    virtual void vb1(){}
    int vb;
};

class Base1 : virtual public VBase {
public:
    virtual void v1() {}
    int b1;
};

class Base2 : virtual public VBase {
public:    
    virtual void v2() {}
    int b2;
};

class Derived : public Base1, public Base2 {
public:    
    virtual void v3() {}
    int d;
};

  结果分析:虚继承后,基类中多了一张虚类表(vbtable),该虚类表记录的是到虚类的偏移量,好比4+24 = 28。而虚函数表的状况一如咱们以前讨论。再细看,咱们发现虚基类并不做为继承类的一部分,而是由虚类表来找到。

相关文章
相关标签/搜索