C++對象內存模型2 (虛函數,虛指針,虛函數表)(轉)

class A {
public:
    virtual void vfunc1();
    virtual void vfunc2();
    void func1();
    void func2();
    virtual ~A();
private:
    int m_data1, m_data2;
}; 

class B : A {
public:
    virtual void vfunc1();;
    void func2();
    virtual ~B();
private:
    int m_data3;
};

class C : B {
public:
    virtual void vfunc1();
    void func();
private:
    int m_data1, m_data4;
};

注:在子類中出現與父類相同名稱的變量和非虛函數不是最佳實踐,這裏是爲了說明其內存結構。ide

對其分析以下:函數

1. 每一個含有虛函數的類在內存中多一根指針(vptr),見圖中a,b,c對象中第一個位置,存儲的是虛函數表(vtbl)所在的位置。佈局

2. 虛函數表(vtbl)存儲着全部虛函數的位置(地址),因爲其動態綁定特性,在覆寫(override)後在子類中存儲的虛函數位置與父類中不相同。this

3. 分析上述代碼, B繼承A,因此A中的數據部分也被B繼承下來,同時B添加上了本身的數據部分m_data3,加之vptr,組成了B左側的內存佈局。spa

  A中的虛函數vfunc1(),vfunc2()能夠被覆寫和動態綁定。指針

  因此在B中,vfunc1()被覆寫,其vtbl中對應項指向了新的函數的位置(亮藍色)。vfunc2()未被覆寫,仍然指向原先位置(深藍色)。code

  C與B同理,vfunc1()被覆寫,其vtbl中對應項指向了新的函數的位置(橘黃色)。vfunc2()未被覆寫,仍然指向原先位置(深藍色)。對象

非虛函數靜態綁定,存儲在單獨的內存空間(code memory section,灰色函數部分),調用時把對象的this指針,傳給一個invisible參數,以便肯定誰在調用函數。blog

4. 調用虛函數的語句的C語言形式如圖中下部分所示,其中n表示對應的函數在第幾個位置(編譯器在創建虛函數表的時候已知),從而實現動態綁定。繼承

相關文章
相關標籤/搜索