C++ 類的繼承與派生(六)派生類的構(gòu)造和析構(gòu)函數(shù)

注意:本文中代碼均使用 Qt 開發(fā)編譯環(huán)境

派生類的目的是為了發(fā)展,派生類繼承了基類的成員,實現(xiàn)了原有代碼的重用,這只是一部分,而代碼的擴充才是最主要的,只有通過添加新的成員,加入新的功能,類的派生才有實際意義。

派生類的構(gòu)造函數(shù)只負(fù)責(zé)對新增的成員進行初始化,對所有從基類繼承來的成員,其初始化工作還是由基類的構(gòu)造函數(shù)完成。同樣,對派生類對象的掃尾、清理工作,也需要加入新的的析構(gòu)函數(shù)。

基類的構(gòu)造函數(shù)并沒有繼承下來,要完成這些工作,就必須給派生類添加新的構(gòu)造函數(shù)。派生類的構(gòu)造函數(shù)需要以合適的初值作為參數(shù),其中一些參數(shù)要用于對派生類新增成員進行初始化,另一些參數(shù)要分別傳遞給基類的構(gòu)造函數(shù)和對象成員的構(gòu)造函數(shù),用于初始化相應(yīng)的成員。

什么時候需要聲明派生類的構(gòu)造函數(shù)?###

如果基類聲明了帶有形參表的構(gòu)造函數(shù)時,派生類就應(yīng)當(dāng)聲明構(gòu)造函數(shù),提供一個將參數(shù)傳遞給基類構(gòu)造函數(shù)的途徑,保證在基類進行初始化時能夠獲得必要的數(shù)據(jù)。當(dāng)然,如果基類沒有聲明構(gòu)造函數(shù),派生類也可以不聲明構(gòu)造函數(shù),全部采用默認(rèn)構(gòu)造函數(shù),這時新增成員的初始化工作可以用其他公有函數(shù)來完成。

派生類構(gòu)造函數(shù)執(zhí)行的一般次序如下:
(1) 調(diào)用基類構(gòu)造函數(shù),調(diào)用順序按照它們被繼承時的順序(從左至右)
(2) 調(diào)用內(nèi)嵌成員對象的構(gòu)造函數(shù),調(diào)用順序按照它們在類中聲明的順序
(3) 派生類構(gòu)造函數(shù)體中的內(nèi)容

其中,如果派生類中新增成員中有內(nèi)嵌的對象,第二步調(diào)用才會執(zhí)行,否則,就直接跳轉(zhuǎn)到第三步。

示例:

#include <QCoreApplication>
#include <QDebug>

class B1
{

public:
    B1(int i){qDebug()<<"Constructing B1 "<<i;}    //基類B1,構(gòu)造函數(shù)有參數(shù)
};

class B2
{

public:
    B2(int j){qDebug()<<"Constructing B2 "<<j;}    //基類B2,構(gòu)造函數(shù)有參數(shù)
};

class B3
{

public:
    B3(){qDebug()<<"Constructing B3 *";}    //基類B3,構(gòu)造函數(shù)無參數(shù)
};

class C : public B2,public B1,public B3        //派生類C,注意此處的繼承順序!
{

public:
    C(int a,int b, int c,int d):B1(a),memberB2(d),memberB1(c),B2(b){}

private:
    B1 memberB1;
    B2 memberB2;
    B3 memberB3;
};

int main()
{
    C obj(1,2,3,4);
    return 0;
}

注意:
首先,這里并沒有列出全部的基類和成員對象,由于B3類只有默認(rèn)構(gòu)造函數(shù),不需要給它傳遞參數(shù),因此,基類B3以及B3類成員對象memberB3就不必列出。

其次,基類名和成員對象名的順序是隨意的。這個派生類構(gòu)造函數(shù)的函數(shù)體為空,可見實際上只是起到了傳遞參數(shù)和調(diào)用基類及內(nèi)嵌對象構(gòu)造函數(shù)的作用。

輸出:


輸出結(jié)果

基類構(gòu)造函數(shù)的調(diào)用順序是按照派生類定義時的順序,因此應(yīng)該是先B2,再B1,再B3,而內(nèi)嵌對象的構(gòu)造函數(shù)調(diào)用順序應(yīng)該是按照成員在類中聲明的順序,應(yīng)該是先B1,再B2,再B3,程序運行的結(jié)果也完全印證這種分析。

拷貝構(gòu)造函數(shù)###

如果要為派生類編寫拷貝構(gòu)造函數(shù),則需要為基類相應(yīng)的拷貝構(gòu)造函數(shù)傳遞參數(shù)。例如假設(shè)C類是B類的派生類,C類的拷貝構(gòu)造函數(shù)形式如下:
C::C(C &c1):B(c1){…}

B類的拷貝構(gòu)造函數(shù)參數(shù)類型應(yīng)該是B類對象的引用,為什么要用C類對象的引用c1作為參數(shù)呢?
這是因為類型兼容規(guī)則在這里起到了作用:可以用派生類的引用去初始化基類的引用。因此當(dāng)函數(shù)的形參是基類的引用時,實參可以是派生類的引用。

析構(gòu)函數(shù)###

從下面的實例輸出結(jié)果可以簡單的看出派生類析構(gòu)函數(shù)執(zhí)行次序和構(gòu)造函數(shù)正好嚴(yán)格相反。

在上面的示例基礎(chǔ)上稍加調(diào)整:

#include <QCoreApplication>
#include <QDebug>

class B1
{

public:
    B1(int i){qDebug()<<"Constructing B1 "<<i;}    //基類B1,構(gòu)造函數(shù)有參數(shù)
    ~B1(){qDebug()<<"Destructing B1";}
};

class B2
{

public:
    B2(int j){qDebug()<<"Constructing B2 "<<j;}    //基類B2,構(gòu)造函數(shù)有參數(shù)
    ~B2(){qDebug()<<"Destructing B2";}
};

class B3
{

public:
    B3(){qDebug()<<"Constructing B3 *";}    //基類B3,構(gòu)造函數(shù)無參數(shù)
    ~B3(){qDebug()<<"Destructing B3";}
};

class C : public B2,public B1,public B3        //派生類C,注意此處的繼承順序!
{

public:
    C(int a,int b, int c,int d):B1(a),memberB2(d),memberB1(c),B2(b){}

private:
    B1 memberB1;
    B2 memberB2;
    B3 memberB3;
};

int main()
{
    C obj(1,2,3,4);
    return 0;
}

輸出結(jié)果:


輸出結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn):C++繼承中構(gòu)造函數(shù)、析構(gòu)函數(shù)調(diào)用順序及虛析構(gòu)函數(shù) 1.構(gòu)造函數(shù) 大家都知道構(gòu)造函數(shù)里就可以調(diào)用成員變量,而繼...
    資深小夏閱讀 822評論 0 0
  • C++文件 例:從文件income. in中讀入收入直到文件結(jié)束,并將收入和稅金輸出到文件tax. out。 檢查...
    SeanC52111閱讀 3,092評論 0 3
  • 類的繼承與派生 類的繼承就是新類由已經(jīng)存在的類獲得已有特性,類的派生是由已經(jīng)存在的類產(chǎn)生新類的過程。已有類叫做基類...
    Mr希靈閱讀 689評論 0 1
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,663評論 1 51
  • 臥槽睡不著 那就告誡自己一句話,先成為朋友,能聊到一起,玩到一起,再看其它吧。 接觸久了才能真正了解一個人。 別忘...
    waitbutwhy閱讀 390評論 0 0

友情鏈接更多精彩內(nèi)容