1. 程式人生 > >C++多型的原理

C++多型的原理

在講原理之前,首先介紹靜態聯編和動態聯編:

靜態聯編:再編譯階段確定程式執行的程式碼,比如普通的變數定義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; }