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;
};

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

對其分析如下:

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

2. 虛函數表(vtbl)存儲着所有虛函數的位置(地址),由於其動態綁定特性,在覆寫(override)后在子類中存儲的虛函數位置與父類中不相同。

3. 分析上述代碼, B繼承A,所以A中的數據部分也被B繼承下來,同時B添加上了自己的數據部分m_data3,加之vptr,組成了B左側的內存布局。

  A中的虛函數vfunc1(),vfunc2()可以被覆寫和動態綁定。

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

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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM