C++ 類對象的初始化順序 ZZ


C++構造函數調用順序

1.     創建派生類的對象,基類的構造函數優先被調用(也優先於派生類里的成員類);

2.    如果類里面有成員類,成員類的構造函數優先被調用;(也優先於該類本身的構造函數)

3.     基類構造函數如果有多個基類,則構造函數的調用順序是某類在類派生表中出現的順序而不是它們在成員初始化表中的順序;

4.     成員類對象構造函數如果有多個成員類對象,則構造函數的調用順序是對象在類中被聲明的順序而不是它們出現在成員初始化表中的順序;

5.     派生類構造函數,作為一般規則派生類構造函數應該不能直接向一個基類數據成員賦值而是把值傳遞給適當的基類構造函數,否則兩個類的實現變成緊耦合的(tightly coupled)將更加難於正確地修改或擴展基類的實現。(基類設計者的責任是提供一組適當的基類構造函數)

綜上可以得出,初始化順序:

父類構造函數–>成員類對象構造函數–>自身構造函數

其中成員變量的初始化與聲明順序有關,構造函數的調用順序是類派生列表中的順序。
析構順序和構造順序相反

下面是最近筆試的某網絡公司的題目:

#include <iostream>
using namespace std;

class A
{
      public:
            A(){ cout<<“A”<<endl;}
            virtual ~A(){ cout<<“~A”<<endl; }
};

class B: public A
{
      public:
             B(){ cout<<“B”<<endl;}
             ~B() {cout<<“~B”<<endl; }
      private:
              A a;
};

class C: public A, public B     //類在派生表中的繼承列表
{
      public:
              C() {cout<<“C”<<endl;}
              ~C() {cout<<“~C”<<endl; }
      private:
              B b;
      public:
             A a;
};

int main()
{
    C * p = new C;
    delete p;
   
    system(“PAUSE”);
    return 0;
}

結果和分析:

A          //1 父類A的構造函數
A         //2 父類B中A的構造函數
A         //3 父類B中成員變量b初始化 (調用父類A的構造函數)
B         //4  父類B中成員變量b初始化 (調用父類B的構造函數)
A        //5   C中成員變量b 的構造
A
B
A         //6 C中成員變量a的構造
C         //7 C的構造函數最后調用 (finally ,-__-|||)
~C
~A
~B
~A
~A
~B
~A
~A
~A

====================================

綜上可以看出,1~4 按照在派生表中的出現次序進行初始化,首先調用父類的構造函數

                          5, 6 調用 成員變量的構造函數

                         7 調用自身的構造函數

PS:更復雜的情況,可以試下虛繼承。

在有虛繼承和一般繼承存在的情況下,優先虛繼承

例如class C: public B, virtual public A

則先調用A的構造函數,再調用B的構造函數

=================================================================================================================================

http://sun.solrex.org/?p=254


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM