C++ 虛繼承衍生類別建構函式的寫法__Jquery

來源:互聯網
上載者:User
昨天做題時候發現的問題

普通的繼承中,我們可以在當前類(C)建構函式的初始化表中指明如何去構造直接父類(B),然後在該父類(B)建構函式的初始化表中指明如何構造祖先類(A)。


範例程式碼

class A{public:    A() {}    A(int d):data(d) {}private:    int data;};class B : public A{public:    B() {}    B(int x):A(x) {}};class C : public B{public:    C() {}    C(int x):B(x) {}};


這樣的寫法是正確的,在建立一個 C 類型的執行個體時,程式會根據其建構函式的選擇以及參數化表層層找到最上層的類,然後依次往下執行建構函式進行初始化。


但是在繼承鏈中如果存在虛繼承的話或許就不是這樣了。

程式中有四個類: animal、aqu_animal、amp_animal、test

其中類之間的繼承關係如下,除 test 以外其他繼承都採用虛繼承的方式。


範例程式碼

這裡還是按照原來的思路進行初始化的工作

#include <iostream>#include<stdio.h>using namespace std;class animal{protected:    int height;    int weight;    char sex;public:    animal()    {        cout<<"animal()"<<endl;    }    animal(int h,int w,char s):        height(h),weight(w),sex(s)    {        cout<<"animal(int h,int w,char s)"<<endl;    }};class aqu_animal:virtual public animal{protected:    int swimming_speed;public:    aqu_animal()    {        cout<<"aqu_animal()"<<endl;    }    aqu_animal(int h,int w,char s,int s_p):        animal(h,w,s),swimming_speed(s_p)    {        cout<<"aqu_animal(int h,int w,char s,int s_p)"<<endl;    }};class amp_animal:virtual public aqu_animal{public:    amp_animal()    {        cout<<"amp_animal()"<<endl;    }    amp_animal(int h,int w,char s,int s_p,int r):aqu_animal(h,w,s,s_p),running_speed(r)    {        cout<<"amp_animal(int h,int w,char s,int s_p,int r)"<<endl;    }    void show()    {        cout<<"height:"<<height<<endl;        cout<<"weight:"<<weight<<endl;        cout<<"sex:"<<sex<<endl;        cout<<"swimming_speed:"<<swimming_speed<<endl;        cout<<"running_speed:"<<running_speed<<endl;    }private:    int running_speed;};class test:public amp_animal{public:    test() {}    test(int h,int w,char s,int s_p,int r):amp_animal(h,w,s,s_p,r)    {        cout<<"test(int h,int w,char s,int s_p,int r)"<<endl;        cout<<"----------------"<<endl;        amp_animal::show();    }};int main(){    test t(50,20,'m',100,120);    return 0;}


執行結果

animal()aqu_animal()amp_animal(int h,int w,char s,int s_p,int r)test(int h,int w,char s,int s_p,int r)----------------height:4309616weight:7012244sex:swimming_speed:1978756045running_speed:120

可以看到,除了 running_speed 正常外其他的變數都沒有被正常賦值。


在函數的調用中,我們發現 test 類中的 test(int h,int w,char s,int s_p,int r) 正常執行了,並且它所附帶的初始化表中的建構函式同樣也被執行了( amp_animal(int h,int w,char s,int s_p,int r) )。

而在 amp_animal 類中利用 amp_animal(int h,int w,char s,int s_p,int r) 構造時的父類 aqu_animal 建構函式 aqu_animal(int h,int w,char s,int s_p) 並沒有被執行,同樣 animal 類中的 animal(int h,int w,char s) 也沒有被執行,實際上都是調用了它們預設的建構函式。


原因以及解決方案

在 C++ 中,如果繼承鏈上存在虛繼承的基類,則最底層的子類要負責完成該虛基類部分成員的構造。

即我們需要顯式調用虛基類的建構函式來完成初始化,如果不顯式調用,則編譯器會調用虛基類的預設建構函式,若虛基類中沒有定義的預設建構函式,則會編譯錯誤。

因為如果不這樣做,虛基類部分會在存在的多個繼承鏈上被多次初始化。

很多時候,對於繼承鏈上的中間類,我們也會在其建構函式中顯式調用虛基類的建構函式,因為一旦有人要建立這些中間類的對象,我們要保證它們能夠得到正確的初始化。


改法

#include <iostream>#include<stdio.h>using namespace std;class animal{protected:    int height;    int weight;    char sex;public:    animal()    {        cout<<"animal()"<<endl;    }    animal(int h,int w,char s):        height(h),weight(w),sex(s)    {        cout<<"animal(int h,int w,char s)"<<endl;    }};class aqu_animal:virtual public animal{protected:    int swimming_speed;public:    aqu_animal()    {        cout<<"aqu_animal()"<<endl;    }    aqu_animal(int h,int w,char s,int s_p):        animal(h,w,s),swimming_speed(s_p)    {        cout<<"aqu_animal(int h,int w,char s,int s_p)"<<endl;    }};class amp_animal:virtual public aqu_animal{public:    amp_animal()    {        cout<<"amp_animal()"<<endl;    }    amp_animal(int h,int w,char s,int s_p,int r):aqu_animal(h,w,s,s_p),running_speed(r),animal(h,w,s)    {        cout<<"amp_animal(int h,int w,char s,int s_p,int r)"<<endl;    }    void show()    {        cout<<"height:"<<height<<endl;        cout<<"weight:"<<weight<<endl;        cout<<"sex:"<<sex<<endl;        cout<<"swimming_speed:"<<swimming_speed<<endl;        cout<<"running_speed:"<<running_speed<<endl;    }private:    int running_speed;};class test:public amp_animal{public:    test() {}    test(int h,int w,char s,int s_p,int r):amp_animal(h,w,s,s_p,r),aqu_animal(h,w,s,s_p),animal(h,w,s)    {        cout<<"test(int h,int w,char s,int s_p,int r)"<<endl;        cout<<"----------------"<<endl;        amp_animal::show();    }};int main(){    test t(50,20,'m',100,120);    return 0;}


注意 test 的建構函式初始化表中我們顯式的調用了其間接父類的建構函式。


執行結果

animal(int h,int w,char s)aqu_animal(int h,int w,char s,int s_p)amp_animal(int h,int w,char s,int s_p,int r)test(int h,int w,char s,int s_p,int r)----------------height:50weight:20sex:mswimming_speed:100running_speed:120

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.