2

クラス A と クラス B があります。クラス C はクラス B から派生し、クラス A オブジェクトを構成として持ちます。http://ideone.com/JGT48M

#include "iostream"
using namespace std;

class A {
  int i;
public:
  A(int ii) : i(ii) {
      cout << "\n Constructor of A is called \n";

  }
  ~A() {
      cout << "\n destructor  of A is called \n";
  }
  void f() const {}
};

class B {
  int i;
public:
  B(int ii) : i(ii) {
      cout << "\n Constructor of B is called \n";
  }
  ~B() {
      cout << "\n destructor  of B is called \n";
  }
  void f() const {}
};

class C : public B {
  A a;
public:
  C(int ii) : a(ii), B(ii) {
      cout << "\n Constructor of C is called \n";
  }
  ~C() {
  cout << "\n destructor  of C is called \n";
  } // Calls ~A() and ~B()
  void f() const {  // Redefinition
    a.f();
    B::f();
  }
};

int main() {
  C c(47);
} ///:~

コンストラクターは、派生クラスのコンストラクターでの呼び出し方法に基づいて呼び出されることを読みました。つまり、REF_BASE1 と REF_BASE2 から派生した REF というクラスが存在するということです。

 REF (int ii) : REF_BASE2(ii), REF_BASE1 (ii) {

REF_BASE2 が最初に呼び出され、次に REF_BASE1 が呼び出され、次に REF コンストラクターが呼び出されることを意味します。そして、それを次のように定義した場合

REF (int ii) : REF_BASE1(ii), REF_BASE2 (ii) {

REF_BASE1 が最初に呼び出され、次に REF_BASE2 が呼び出され、次に REF コンストラクターが呼び出されることを意味します。

ただし、上記の私のプログラムでは、内部構成変数 A によって最初に初期化され、次に B を初期化する必要があることを明示的に「間違って」述べていますが、コンパイラは正しい方法でそれを行いますが、間違いを知らせません

派生クラスのコンストラクター初期化リストで指定した順序に関係なく、上記のプログラムの出力は

Constructor of B is called 

 Constructor of A is called 

 Constructor of C is called 

 destructor  of C is called 

 destructor  of A is called 

 destructor  of B is called 

私の質問は 1) コンパイラが文句を言わないのはなぜですか? または私は正しいですか?2) 派生コンストラクターの順序が厳密に守られていませんか?

4

1 に答える 1

5

2 番目の質問から始めます。

2) 派生コンストラクターの順序が厳密に守られていませんか?

順序は、コンストラクターの初期化リストに表示される順序ではなく、基本クラスがクラス定義に表示される順序です。

したがって、クラス定義が次のようになっているとします。

struct A : B, C
{
    // ...
};

次に、 のコンストラクターの初期化リストで指定した順序に関係なくB、 のコンストラクターが のコンストラクターの前に呼び出されます。CA

C++11 標準の 12.6.2/10 項では、次のように指定されています。

非委任コンストラクターでは、初期化は次の順序で進行します。

— 最初に、最も派生したクラス (1.8) のコンストラクターに対してのみ、仮想基底クラスは、基底クラスの有向非巡回グラフの深さ優先の左から右への走査に現れる順序で初期化されます。 -to-right」は、派生クラス base-specifier-list 内の基底クラスの出現順序です。

— 次に、直接基底クラスは、base-specifier-list に表示される宣言順に初期化されます (mem-initializer の順序に関係なく)

— 次に、非静的データ メンバーは、クラス定義で宣言された順序で初期化されます (これも mem-initializer の順序に関係なく)。

— 最後に、コンストラクター本体の複合ステートメントが実行されます。

最初の質問:

1) コンパイラが文句を言わないのはなぜですか?

コンパイラーは、コンストラクター初期化子リストの初期化順序が基本クラス リストの初期化順序と異なること-Wallを警告する場合があります (GCC は で行います) が、そうする必要はありません。結局、後者だけが重要です。

于 2013-06-01T13:29:28.680 に答える