1. 程式人生 > >C/C++—— 在建構函式中呼叫虛擬函式能實現多型嗎(Vptr指標初始化的過程分析)

C/C++—— 在建構函式中呼叫虛擬函式能實現多型嗎(Vptr指標初始化的過程分析)

問題引入:

比如:如果我們想在父類的建構函式中呼叫虛擬函式,當定義子類物件的時候,父類的建構函式中的虛擬函式執行的是子類中的函式。
在下面的例子中,定義子類物件的時候,在父類建構函式中的print虛擬函式執行的不是子類中的print函式,而是父類中的print函式。

#include <iostream>
using namespace std;

class Parent
{
public:
    //在父類的建構函式裡面,呼叫虛擬函式,不會產生多型。。
    //言外之意:不會呼叫子類的虛擬函式。。。。
    Parent(int a = 0)
    {
        print(); //定義子類物件的時候,想該print函式呼叫的是子類的print函式。。結果表明呼叫的是父類的print函式
this->a = a; } //第一個動手腳的地方 編譯器應該對這個虛擬函式特殊處理。。。。 virtual void print() { cout<< "Parent." <<endl; } private: int a; }; class Child : public Parent { public: Child(int b = 0) { this->b = b; } virtual void print() { cout
<< "Child."<<endl; } private: int b ; }; int main() { Child c1; return 0; }

輸出:
Parent.
輸出為Parent.表明呼叫的是父類的虛擬函式print,不是子類的虛擬函式print。

原因分析:

主要是參考該部落格的最後一部分分析:物件中的VPTR指標什麼時候被初始化?

Vptr指標初始化的過程:
1.物件在建立的時,由編譯器對VPTR指標進行初始化
2.只有當物件的構造完全結束後VPTR的指向才最終確定
3.父類物件的VPTR指向父類虛擬函式表
4.子類物件的VPTR指向子類虛擬函式表

當定義一個子類物件的時候比較麻煩,因為構造子類物件的時候會首先呼叫父類的建構函式然後再呼叫子類的建構函式。當呼叫父類的建構函式的時候,此時會建立Vptr指標(也可以認為Vptr指標是屬於父類的成員,所以在子類中重寫虛擬函式的時候virtual關鍵字可以省略,因為編譯器會識別父類有虛擬函式,然後就會生成Vptr指標變數),該指標會指向父類的虛擬函式表;然後再呼叫子類的建構函式,此時Vptr又被賦值指向子類的虛擬函式表。
(執行父類的建構函式的時候Vptr指標指向的是父類的虛擬函式表,所以只能執行父類的虛擬函式)
上面的過程是Vptr指標初始化的過程。
這是因為這個原因,在建構函式中呼叫虛擬函式不能實現多型。