先看下面這個簡單的例子,我們建立乙個基類(base class),通過簡單的繼承(inherit)產生兩個派生類(derived class),然後通過乙個基類的指標去呼叫這兩個派生類,並且呼叫類中的函式。
class base
void show2()
};class derived1: public base
void show2()
};class derived2: public base
};void printresult(void)
輸出結果如下:
base
class
base
class
show 2
derived
class 1
base
class
show 2
derived
class 2
基類中定義了虛函式show(),兩個派生類都對重新定義了show(),雖然是使用基類的指針對類中show()進行呼叫,但是,實際執行的是各個類中定義的show()。但是作為對比,雖然derived1中對show2()也進行了定義,但是兩次呼叫所執行的都是base中定義的show2()。原因就在於兩者性質不同,虛函式的入口是儲存在類的虛表中,程式執行的時候才能確定,也就是晚繫結,而show2(),是直接與類進行繫結的,在程式編譯的時候就完成了繫結,也就是早繫結。
本文剩餘的部分幾乎全部用來討論虛表的構建和記憶體結構,來搞清楚繼承的時候到底發生了什麼。
這次換乙個稍微複雜一點的:
class base
virtual
void b()
virtual
void c()
};
使用gdb進行除錯,列印出類所佔記憶體的資料:
(gdb) x /4xg 0x400f70
0x400f70 <_ztv4base+16>: 0x0000000000400d24 0x0000000000400d4e
0x400f80 <_ztv4base+32>: 0x0000000000400d78 0x6465766972654437
(gdb) x /4xg 0x400f30
0x400f30 <_ztv7derived+16>: 0x0000000000400da2 0x0000000000400d4e
0x400f40 <_ztv7derived+32>: 0x0000000000400d78 0x0000000000000000
從記憶體布局看C 虛繼承的實現原理
今天講的是虛基類和虛繼承,我們就先用上面介紹的命令提示工具檢視一下普通多繼承子類的記憶體布局,可以跟後文虛繼承子類的記憶體布局情況加以比較。我們新建乙個名叫normalinheritance的cpp檔案,輸入一下內容。普通繼承 沒有使用虛基類 基類a class a class b public a...
從類記憶體看虛表
結合文章看 情形一 單繼承,派生類中只有乙個虛表 include stdafx.h using namespace std include 基類a 單繼承中我們可以看出,派生類中只有乙個虛表,是從基類繼承過來的虛表,基類的虛表裡的內容先儲存到虛表中,接著如果派生類重寫了基類的虛函式則重新覆蓋更新基類...
從記憶體和物件的角度看C 類的靜態
提綱 1,c 的記憶體分割槽 stack heap和靜態儲存區 2,靜態物件和例項物件 3,使用規則 4,應用場景 一 c 的記憶體分割槽和物件模型 參考 c primer plus 第9章 記憶體模型和命名空間 c 中用 持續性 作用域和鏈結性 三個屬性來表徵其儲存特性,包括變數和函式。c 的記憶...