1. 程式人生 > >關於類繼承的構造與析構調用分析

關於類繼承的構造與析構調用分析

fff 調用父類 派生類的構造函數 臨時 臨時對象 構造函數 back 基類 原因分析

  總體結論:派生類的構造函數在創建對象時調用,調用順序如下

       1.調用虛基類的構造函數(若有多個虛基類,調用順序為繼承的順序。);

       2.調用基類的構造函數(若有多個基類,調用順序為繼承的順序。);

       3.調用類類型的成員對象的構造函數(調用順序為定義的順序);

       4.調用自身的構造函數。

       析構函數的調用順序一般和構造函數的調用順序相反,但分如下幾種情況:

       1.當父類的指針 new一個子類的臨時對象時。若父類的析構不是虛函數,則delete的時候不調用子類的析構,只調用父類的析構;

        若父類的析構是虛函數,則delete的時候先調用子類的析構,後調用父類的析構;

       2.當子類的指針 new一個子類的臨時對象時。不管父類的析構是否為虛函數,delete的時候都會先調用子類的析構,後調用父類的析構;

  代碼驗證

      

class A {
public:
    A() {
        cout << " A" << endl;
    }
    ~A() {  //不是虛函數
        cout << "~ A" << endl;
    }
};

class B {
public:
    B() {
        cout << "
B" << endl; } ~B() { //不是虛函數 cout << "~ B" << endl; } }; class C:public A,public B { public: C() { cout << " C" << endl; } ~C() { cout << "~ C" << endl; } }; int main() { A *a = new
C(); delete a; return 0; } /*運行結果 : A B C ~A */
class A {
public:
    A() {
        cout << " A" << endl;
    }
    virtual ~A() {  //是虛函數
        cout << "~ A" << endl;
    }
};

class B {
public:
    B() {
        cout << " B" << endl;
    }
    virtual ~B() {  //是虛函數
        cout << "~ B" << endl;
    }
};

class C:public A,public B
{
public:
    C() {
        cout << " C" << endl;
    }
    ~C() {
        cout << "~ C" << endl;
    }
};

int main() {
    A *a = new C();
    delete a;
    return 0;
}
/*運行結果 :
A
B
C
~ C
~ B
~ A
*/
class A {
public:
    A() {
        cout << " A" << endl;
    }
    virtual ~A() {  //是虛函數
        cout << "~ A" << endl;
    }
};

class B {
public:
    B() {
        cout << " B" << endl;
    }
    virtual ~B() {  //是虛函數
        cout << "~ B" << endl;
    }
};

class C:public A,public B
{
public:
    C() {
        cout << " C" << endl;
    }
    ~C() {
        cout << "~ C" << endl;
    }
};

int main() {
    C *c = new C();
    delete c;
    return 0;
}
/*運行結果 :
A
B
C
~ C
~ B
~ A
*/
class A {
public:
    A() {
        cout << " A" << endl;
    }
       ~A() {  //不是虛函數
        cout << "~ A" << endl;
    }
};

class B {
public:
    B() {
        cout << " B" << endl;
    }
         ~B() {  //不是虛函數
        cout << "~ B" << endl;
    }
};

class C:public A,public B
{
public:
    C() {
        cout << " C" << endl;
    }
    ~C() {
        cout << "~ C" << endl;
    }
};

int main() {
    C *c = new C();
    delete c;
    return 0;
}
/*運行結果 :
A
B
C
~ C
~ B
~ A
*/    

  原因分析

      1.當父類析構函數不是虛函數時,進行編譯時調用,只調用自身的析構函數。

      2.當父類析構函數是虛函數時,進行運行時調用,無論指針指的那個對象,系統都會調用相關類的析構函數。

       程序中最好把父類的析構函數聲明虛函數,這樣所有子類的析構函數也為虛函數,也為了防止內存泄露。

關於類繼承的構造與析構調用分析