深入理解C 多型及實現機制

2021-06-23 02:46:08 字數 3944 閱讀 5268

1、多型

多型是物件導向程式的核心概念。c++的多型實現是基於繼承和虛函式,這種實現稱為動態多型性。多型性可以簡單的概括為「1個介面,多種方法」,在程式執行的過程中才決定呼叫的機制,簡單的說就是可以通過父類指標呼叫子類的函式,可以讓父類指標有多種形態。

2、問題引入

先看下面幾個問題:

//code sample1

class a

};class b :public a

};int main(void)

};class b:public a

};int main(void)

};class b:virtual public a

};int main(void)

virtual void funca(){}

virtual void func()

}; classb : public a

virtual void funcb(){}

virtual void func()

}; int main(void)

輸出的結果是:class b's func.

多型就是多種狀態,乙個事物可能有多種表現形式,譬如動物,有十二生肖甚至更多的表現形式。當基類裡實現了某個虛函式,但派生類沒有實現,那麼類 b 的例項裡的虛函式表中放置的就是 &a::func。此外,派生類也實現了虛函式,那麼類 b 例項裡的虛函式表中放置的就是 b::func。a *pa = new b; 因為 b 實現了 func,那麼它被放入 a 例項的虛函式表中,從而代替 a 例項本身的虛函式。pa->func(); 呼叫的結果就不稀奇了,這是虛函式機制帶來的。

class a 和 class b 的記憶體布局和 vptr 可能是下面的樣子:

———-

|   int a |

———-

|    vptr | ——–>|      &a::funca()

———-             ————————————————-

|      &a::func()

————————————————-

———-

|   int a |

———-

|    vptr | ——–>|     &a::funca() 依舊是 a 的虛函式

———-             ————————————————-

|   int b |              |     &b::func() a::func()

———-             ————————————————-

|     &b::funcb()

————————————————-

總結一下:

4、多重繼承

class a

int a;

void fooa(){}

virtual void func();

virtual void funca()};

class b

int b;

void foob(){}

virtual void func();

virtual void funcb()};

class c : public a,public b

int c;

void fooc(){}

virtual void func();

virtual void funcc()};

int main(void)

當用基類的指標指向乙個派生類的實體地址,基類有兩種情況,一種是 class a 和 class b,如果是 a,問題容易解決,幾乎和上面單一繼承情況類似;但倘若是 b,要做位址上的轉換,情況會比前者複雜。先展現class a,b,c 的記憶體布局和 vptr:

———-

|   int a |

———-

|    vptr | ——–>|      &a::~a()

———-             ————————————————-

|      &a::func()

————————————————-

|      &a::funca()

————————————————-

———-

|   int b |

———-

|    vptr | ——–>|     &b::~b()

———-             ————————————————-

|     &b::func()

————————————————-

|     &b::funcb()

————————————————–

|      &c::~c() &a::~a()

———-             ————————————————-

|   int a |               |      &c::func() &a::func()

———-             ————————————————-

———-             |      &c::funcc()

|    vptr | ——–>————————————————-

———-             |      &a::funca()

———-             ————————————————-

|   int b |               |      &b::funcb() 跳

———-             ————————————————-

———-

|    vptr | ——–>|     &c::~c() &b::~b() 跳

———-             ————————————————-

|   int c |               |     &c::func() &b::func() 跳

———-             ————————————————-

|     &b::funcb()

多重繼承中,會有保留兩個虛函式表,乙個是與 a 共享的,乙個是與 b 相關的,他們都在原有的基礎上進行了修改:

對於 a 的虛函式表:

對於 b 的虛函式表:

int main(void)

輸出結果是:

c func.

c func.

funcc.

c destruction

b destruction

a destruction

c destruction

b destruction

a destruction

c destruction

b destruction

a destruction

7 行和 8 行的行為有很大的區別,7 行的呼叫和上面的單一繼承的情況類似,不贅述。8 行的 pb->func(); 中,pb 所指向的是上圖第 9 行的位置,編譯器已在內部做了轉換,也就是 pa 和 pb 所指的位置不一樣,pa 指向的是上圖第 3 行的位置。接著需要注意的是,pb->func(); 呼叫時,在虛函式表中找到的位址需要再進行一次跳轉,目標是 a 的虛函式表中的 &c::func(),然後才真正執行此函式。所以,上面的情況作了指標的調整。

那什麼時候會出現跳,常見的有兩種情況:

右端基類,對應上面的具體是 b,呼叫派生類虛函式,比如 pb->~c() 和 pb->func()

派生類呼叫右端基類的虛函式,比如 pc->funcb()

所以 delete pa; 和 delete pa; 的操作是不一樣的,pb->funcb(); 和 pc->funcb(); 也不一樣。

c++ 為實現多型引入虛函式機制,帶來了空間和執行上的折損。

C 多型的實現機制深入理解

1.用virtual關鍵字申明的函式叫做虛函式,虛函式肯定是類的成員函式。2.存在虛函式的類都有乙個一維的虛函式表叫做虛表。類的物件有乙個指向虛表開始的虛指標。虛表是和類對應的,虛表指標是和物件對應的。3.多型性是乙個介面多種實現,是物件導向的核心。分為類的多型性和函式的多型性。4.多型用虛函式來實...

深入理解Java多型機制

目錄 1,多型的概念?2,存在的條件?3,案列解析?4,應用場景?1,多型的概念 父類引用指向子類物件,通俗點就是,在編譯時不繫結是什麼方法,根據你傳進來的值,是什麼就會執行什麼。2.存在條件 第一,要有繼承 第二,要有方法的重寫 第三,父類引用指向子類物件 3,案列解析 好好體會以下這個案例,通過...

深入理解c 多型實現原理

多型是指通過基類的指標或者引用,在執行時動態呼叫實際繫結物件函式的行為。與之相對應的編譯時繫結函式稱為靜態繫結。多型是物件導向程式設計的核心思想之一,因此我們有必要深入探索一下它的實現原理。理解了原理才能更好的使用。前置條件 現有 如下所示,非常簡單的例子。通過基類的引用呼叫recv函式來觸發多型。...