深刻理解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。而虛函數表的狀況一如咱們以前討論。再細看,咱們發現虛基類並不做爲繼承類的一部分,而是由虛類表來找到。

相關文章
相關標籤/搜索