C++虛函數表(多態的實現)

多態是C++的三大特性之一,是通過虛函數表來實現的。關于虛函數表:

  • 每個含有虛函數的類都有一張虛函數表(vtbl),表中每一項是一個虛函數的地址, 也就是說,虛函數表的每一項是一個虛函數的指針。
  • 如果繼承的父類中有虛函數,那么子類中也會有虛函數表。
  • 沒有虛函數的C++類,是不會有虛函數表的。
  • 一個含有虛函數表的類實例化對象后,對象并不會直接存儲虛函數表,而是在開始的位置存放了一個指向虛函數表的指針。

例1,沒有虛函數的情況

#include <iostream>
using namespace std;
class base
{
     void f(){cout<<"base::f"<<endl;};
     void g(){cout<<"base::g"<<endl;};
     void h(){cout<<"base::h"<<endl;};
};

int main(int argc, const char * argv[]) {
    cout<<"size of Base: "<<sizeof(Base)<<endl;
    return 0;
}

運行結果:size of Base: 1。這里簡單說明一下,C++的成員方法不占用內存,size為1是因為實例化對象需要在內存中分配一塊地址,所以編譯器就分配了一個字節給空類。

例2,有虛函數的情況

class Base {
public:
    
    virtual void f() {cout<<"base::f"<<endl;}
    virtual void g() {cout<<"base::g"<<endl;}
    virtual void h() {cout<<"base::h"<<endl;}
    
};

int main(int argc, const char * argv[]) {
    cout<<"size of Base: "<<sizeof(Base)<<endl;
    return 0;
}

運行結果:size of Base: 8。這8個字節,就是虛函數表的指針。

例3,下面,我們嘗試通過地址偏移的方式來調用虛函數:

class Base {
public:
    
    virtual void f() {cout<<"base::f"<<endl;}
    virtual void g() {cout<<"base::g"<<endl;}
    virtual void h() {cout<<"base::h"<<endl;}
    
};

int main(int argc, const char * argv[]) {
    typedef void(*Func)(void);
    Base b;
    Base *d = &b;    
    long* pvptr = (long*)d; //獲取指向虛函數表的指針,即b對象的首地址
    cout << "vtable address:" << *pvptr << endl; //打印虛函數表的地址

    long* vptr = (long*)*pvptr; //虛函數表的首地址
    Func f = (Func)(*vptr); //虛函數表首地址的值為第一個虛函數的函數指針
    Func g = (Func)(*(vptr+1)); //繼續偏移指針,找到第二個虛函數指針
    Func h = (Func)(*(vptr+2)); //以此類推

   
//  下面這種寫法與上面實際效果相同,只是指針偏移方式不同而已
//  Func f = (Func)vptr[0];  
//  Func g = (Func)vptr[1]; 
//  Func h = (Func)vptr[2]; 
 
    f();
    g();
    h();

    return 0;
}

運行結果:

vtable address:4294975712
base::f
base::g
base::h

參考文章:

下面兩篇文章都講的比較細,從無繼承到多繼承,圖文并茂,有興趣的同學可以學習一下!
http://www.cnblogs.com/Ripper-Y/archive/2012/05/15/2501930.html
http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容