1

クラスの 1 つに対してコンストラクターが呼び出されると、奇妙なエラーが発生します。基本的に、私がやっていることはこれです:

タイプ「B」、「C」の2つのメンバー変数を持つクラス「A」があります。「C」、タイプ「B」のメンバーで開始する必要があります。したがって、コンストラクターは次のようにする必要があります。

A::A():
c(b)
{}

クラスが次のようにレイアウトされている場合、これは正常に機能します。

class A
{
   B b;
   C c;
}

ただし、クラスが次のようにレイアウトされている場合はクラッシュします。

class A
{
   C c;
   B b;
}

私の最初の推測では、コンストラクターで c(b) を初期化する場合、もちろん c の前に b を作成する必要があります。これが正しいかどうかはわかりませんが。メンバー変数が割り当てられるにコンストラクターが呼び出されますか? または、コンストラクターで参照されるメンバー変数が最初に割り当てられ、次に残りの参照されていないメンバー変数がコンストラクターの最後に割り当てられますか (たとえば、コンストラクターで参照されない別のメンバー変数 "C c2" があった場合など)?

私はVisual Studio 2010を使用しています。

4

5 に答える 5

1

メンバーは常に、クラス内で宣言された順序で構築されます。

したがって:

class A
{
   B b;
   C c;
}

完全に構築された後に b を渡しているため、正常に動作します。
これを行う場合:

class A
{
   C c;
   B b;
}

次に、構築されていない B を使用して C を構築しています。値渡しをしている場合、これはおそらくコピー コンストラクターを壊します。参照渡しの場合、C コンストラクター内で使用されている場合は、タイプ 'B' の初期化されていないオブジェクトを使用しています。

于 2012-05-03T21:33:32.207 に答える
1

コンストラクター クラスの順序は、クラス定義内の順序によって異なります。クラス B コンストラクターがまだ呼び出されていないため、2 番目の例は機能しません。

于 2012-05-03T21:33:33.550 に答える
1

したがって、これが機能する方法は次のとおりです。

  1. オブジェクトの構築が始まります。
  2. 非仮想基底クラスは宣言順に構築されます。
  3. 仮想基底クラスは宣言順に構築されます。
  4. 現在のクラス パーツが作成されます (vtable などを初期化します)。
  5. メンバー変数は、初期化子リストではなく、クラス宣言での出現順に構築されます。
  6. コンストラクタ本体が実行されます。
  7. オブジェクトの構築が完了しました。

#3 の配置については間違っている可能性があります。私はめったに仮想ベースを使用せず、このようなものに依存するコードを書くことはめったにありません。なんで?複雑で、そのようなコードは非常に壊れやすいためです。

破壊はまったく逆の順序で発生します。

于 2012-05-03T21:39:14.643 に答える
1

メンバーは、クラス定義に現れる順序で初期化されます。2 番目の例では、c を初期化するときに b は初期化されていません。

メンバー初期化子で順番を間違えると、コンパイラから警告が表示されます。

于 2012-05-03T21:33:01.670 に答える
0

明確にするために、あなたは次のように言いました:

タイプ「B」、「C」の2つのメンバー変数を持つクラス「A」があります。「C」は、タイプ「B」のメンバーで開始する必要があります。したがって、コンストラクターは次のようにする必要があります。

しかし、あなたのコード:

A::A()
: c(b) 
{
} 

あなたの言い回しが言うように、タイプではなく、cメンバー変数で初期化します。bB

多分あなたがしたい:

A::A()
: c(B()) 
{
} 

代わりは?

于 2012-05-03T21:37:14.783 に答える