C++虛擬函式的實現原理
阿新 • • 發佈:2022-04-02
靜態聯編與動態聯編
1. 函式名聯編:將原始碼中的函式呼叫解釋為執行特定的函式程式碼塊,聯編方式分為靜態聯編和動態聯編
2. 靜態聯編是指編譯器在編譯過程中進行聯編,動態聯編是指編譯器必須生成能夠在程式執行時選擇正確虛方法的程式碼
3. 對於非虛擬函式編譯器使用靜態聯編,對於虛擬函式編譯器使用動態聯編
4. 靜態聯編效率更高,因此被設定為C++的預設選擇
指標與引用的相容性
1. C++不允許將一種型別的指標或引用賦值給另一種型別的指標或引用,如double d = 10.5; int * ptr = &d;
是不允許的
2. C++中可以將派生類的指標或引用轉換為基類的引用或指標,即可以使用基類的指標或引用來指向派生類物件,稱為向上轉換,同時這種向上轉換特性是可以傳遞的
3. C++中將基類的指標或引用轉換為派生類的指標或引用稱為向下轉換,向下轉換是不被允許的
虛擬函式工作原理
1. 編譯時,由編譯器建立虛擬函式表,編譯器給每個包含虛擬函式的類建立一個虛擬函式表(vtable),虛擬函式表中的元素存放該類中所有虛擬函式的地址
2. 建立類物件時,編譯器為每個包含虛擬函式的類物件提供了一個虛擬函式表指標(vptr),虛擬函式表指標指向該物件所屬類的虛擬函式表
3. 程式執行時根據物件的型別初始化虛擬函式表指標,使之指向所屬類的虛擬函式表,從而在呼叫虛擬函式時,就能夠找到正確的函式
4. 虛擬函式表是由編譯器自動建立和維護的,每個包含虛擬函式的類物件都會有一個虛擬函式表指標,即虛擬函式表是和類對應的,而虛擬函式表指標是和類物件對應的
5. 虛擬函式表指標通常作為第一個類成員被初始化,由編譯器自動進行初始化操作
class Brass { public: virtual void Withdraw() { cout << "Brass::Withdraw " << endl; } virtual ~Brass() { cout << "~Brass() " << endl; } }; class BrassPluse : public Brass { public: void Withdraw() { cout << "BrassPlus::Withdraw " << endl; } ~BrassPluse() { cout << "~BrassPlus()" << endl; } public: int x; };