天天看點

C++ 派生類構造函數和析構函數

幾個問題

一個類的各資料成員的構造順序?

按他們在類定義中出現的先後順序:先定義者先構造。

類的對象成員的構造函數與類自身的構造函數的執行順序?

先執行對象成員的構造函數,再執行類自身的構造函數。

構造順序與析構順序的關系?

二者順序相反:先構造者,後析構。

構造函數和析構函數用來建立和釋放該類的對象,當這個類是派生類時,其對象的建立和釋放應與其基類對象及成員對象相聯系。

在聲明派生類時,一般還應當自己定義派生類的構造函數和析構函數,因為構造函數和析構函數是不能從基類繼承的

C++ 派生類構造函數和析構函數

派生類對象的建立和初始化與基類對象的建立和初始化有關。即構造派生類對象時,要對其基類資料成員、所含對象成員的資料成員以及其他的新增資料成員一起進行初始化。這種初始化工作是由派生類的構造函數來完成的。

派生類成員包括兩部分:

(1)從基類繼承的成員:由基類構造函數完成

(2)自身定義的成員: 由派生類構造函數完成

C++ 派生類構造函數和析構函數

在派生類中,構造基類資料成員的可能方式:

方式一,在派生類中直接對基類型資料成員初始化:

class BC
{
public:
    BC( )
    {
        x = y = -1;
    }
private:
    int x, y;
};
class DC : public BC
{
public:
    DC( )
    {
        x = y = -1;//錯誤,不能構造基類的私有成員  error C2248: “B::x”: 無法通路 private 成員(在“B”類中聲明)
    }
private:
    string  S;
};      

方式二,顯示調用基類構造函數

class BC
{
public:
    BC( )
    {
        x = y = -1;
    }
private:
    int x, y;
};
class DC : public BC
{
public:
    DC( )
    {
        BC( );//這是構造後才調用,語義錯誤
    }
private:
    string  S;
};      

這樣的程式可以編譯通過,但語意錯誤,這是派生類先構造後,在調用基類的構成函數。

正确構成基類資料成員的方式為:

class BC
{
public:
    BC( )
    {
        x = y = -1;
    }
private:
    int x, y;
};
class DC : public BC
{
public:
    DC( ) : BC( ), S("派生類"), { }//初始化清單
private:
    string  S;
};      

在建立派生類的對象時,需要調用基類的構造函數:初始化派生類對象從基類繼承的成員。在執行一個派生類的構造函數之前,總是先執行基類的構造函數。

調用基類構造函數的兩種方式:

(1)顯式方式:在派生類的構造函數中,通過參數化表為基類的構造函數提供參數

        derived::derived(arg_derived-list):base(arg_base-list)

(2)隐式方式:在派生類/基類的構造函數都預設時,派生類的構造函數則自動調用基類的預設構造函數。

在一個多層次的繼承層次結構中,一個派生類對象的建立時,其構造函數的調用有點類似于多米諾骨牌效應 (domino effect)

C++ 派生類構造函數和析構函數

列出了不同情況下的派生類構造函數要求:

C++ 派生類構造函數和析構函數

上面的例子其實也很好了解,我們知道:在執行一個派生類的構造函數之前,總是先執行基類的構造函數。

1.如果基類中無構造函數,那麼對于派生類來說,不管派生類是何種構造函數,編譯器都會先調用的執行基類的預設構造函數,然後再執行派生類的構造函數。

2.如果基類是一個無預設參數的構造函數,那麼對于派生類一旦沒有構造函數,那麼就不會自動的先構造基類的構造函數,這是不允許的。

3.如果基類中有預設參數的構造函數B(),那麼派生類中沒有構造函數也是允許的,編譯器會自動調用。

通常, 一個基類有一個預設構造函數。

以下做法是有其實際意義的:當一個派生類對象被建立時會引起某個基類的構造函數的執行。

 (這條建議在派生類新增成員依賴于基類成員時展現非常明顯)

class Team
{
public:
    Team(int len =100)
    {
        names = new string[maxno = len ];
        //基類構造函數完成其成員初始化,供派生類構造使用。
    }
protected:
    string* names;
    int     maxno;
};

class BaseballTeam : public Team
{
public:
    BaseballTeam(const string s[], int si)
        : Team(si)//為支援派生類構造本意,必須明确調用基類構造函數。

    {
        for(int i=0; i<si; i++)
            names[i] = s[i];
            //派生類構造函數執行前,基類構造必須完成。

    }
};      

執行構造函數的順序:

1. 基類的構造函數

2. 子對象的構造函數

3. 其他資料成員初始化

繼承下的析構函數 Destructors Under Inheritance

C++ 派生類構造函數和析構函數
class BC
{
public:
    BC( )
    {
        sBC = new char[3];
        cout << "BC allocates 3 bytes.\n";
    }
    ~BC( )
    {
        delete [ ] sBC;
        cout << "BC free 3 bytes.\n";
    }
private:
    char* sBC;
};
class DC : public BC
{
public:
    DC( )
    {
        sDC = new char[5];
        cout << "DC allocates 5 bytes.\n";
    }
    ~DC( )
    {
        delete [ ] sDC;
        cout << "DC free 5 bytes.\n";
    }
private:
    char* sDC;
};
int main( )
{
    DC d;
    cout << “-------” << endl;
    return 0;
}      
C++ 派生類構造函數和析構函數

作者:王陸

出處:https://www.cnblogs.com/wkfvawl/

-------------------------------------------

個性簽名:罔談彼短,靡持己長。做一個謙遜愛學的人!

本站使用「署名 4.0 國際」創作共享協定,轉載請在文章明顯位置注明作者及出處。鑒于部落客處于考研複習期間,有什麼問題請在評論區中提出,部落客盡可能當天回複,加微信好友請注明原因