C++多型的原理
阿新 • • 發佈:2018-11-11
在講原理之前,首先介紹靜態聯編和動態聯編:
靜態聯編:再編譯階段確定程式執行的程式碼,比如普通的變數定義int a = 10,以及函式過載等
動態聯編:在程式執行過程中確定程式執行的程式碼,比如條件判斷語句
多型的原理:
當一個類具有虛擬函式時,編譯器會自動為這個類在全域性區中的常量區新增一個虛擬函式表,這個虛擬函式表儲存著這個類的所有虛擬函式的入口地址,並且會為這個虛擬函式表增加一個vptr指標(也叫虛指標)用於指向這個表,且這個指標會被放在屬性列表首位;vptr指標是在編譯階段由編譯器自動加入的,所以在寫程式碼時是找不到這個指標的
當通過父類指標呼叫子類物件的方法時,編譯器只知道這個指標是父型別的指標,並不知道指向的是子類物件,所以先查詢父類的此方法是否是虛擬函式,如果不是虛擬函式,編譯器會直接確定這個函式的地址(靜態聯編),程式在執行時直接執行此函式並不會進行查表操作,當發現呼叫的父類的這個函式是虛擬函式時,編譯器會自動跳過,等待程式執行時再確定呼叫哪個函式(動態聯編),當程式執行時,呼叫此方法時發現函式地址沒有確定,此時程式會通過子類物件虛指標查詢子類的虛擬函式表,如果子類複寫了父類的虛擬函式,那麼這個複寫的函式會被放入子類的虛擬函式表,進而會被查詢到然後呼叫,如果沒有複寫父類的虛擬函式,那麼父類的虛擬函式會被繼承下來,然後放入子類的虛擬函式表中,進而也會被查詢到然後執行,值的注意的是,虛指標可以被繼承且複寫父類的某個虛擬函式時,無論加不加virtual關鍵字,編譯器都會自動補上virtual關鍵字
以下面程式碼為例:
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> using namespace std; class Parent{ public: virtual void fun1(){ cout << "parent fun1()..." << endl; } void fun2(){ cout << "parent fun2()..." << endl; } }; class Child :public Parent{ public :
void fun1(){//這裡不加virtual關鍵字,編譯器也會自動加上,然後將此函式放入其虛擬函式表中 cout << "child fun1()..." << endl; } virtual void fun2(){ cout << "child fun2()..." << endl; } }; void test(Parent* obj) { obj->fun1();//如果父類fun1不是虛擬函式,這句話函式的地址已經固定了,程式執行時不會再查虛擬函式表,如果父類fun1是虛擬函式,這句話fun1函式地址不確定,程式會進行查表 obj->fun2();//父類的fun2不是虛擬函式,直接確定了fun2的地址,不會進行查表 } int main(void) { Parent* obj = new Child(); test(obj); system("pause"); return 0; }