1

例を次に示します。

class Base {
  Base (const Base & copyFrom) { globalRegister (* this); }
}

class Derived {
  Derived (const Derived & copyFrom) : Base (copyFrom) {}
}

Base のプロパティをコピーするために、Derived の初期化リストに Base のコピー コンストラクターを含めるという提案を読みました (例のように)。

ただし、Base のコピー コンストラクターがそれ自体 (* this) を他のオブジェクト (そのオブジェクトに登録される) に渡すようにしています。実際にオブジェクトがある場合、Derived のコピー コンストラクターの初期化リストで Base の (既定の) コンストラクターを (暗黙的または明示的に) 使用し、Derived のコピー コンストラクターの本体でのみ Base のコピー コンストラクターを呼び出す必要がある場合でしょうか。 Baseのコピーコンストラクターでアタッチできますか? Else - (* this) は有効なオブジェクトですか?

4

2 に答える 2

5

実際にオブジェクトがある場合、Derived のコピー コンストラクターの初期化リストで Base の (既定の) コンストラクターを (暗黙的または明示的に) 使用し、Derived のコピー コンストラクターの本体でのみ Base のコピー コンストラクターを呼び出す必要がある場合でしょうか。 Baseのコピーコンストラクターでアタッチできますか?

なぜあなたはそれをしたいのですか?(ああ、派生クラスのコンストラクターのbody
から基底クラスのコピー コンストラクターを呼び出すことはできません。その初期化リストからのみです。)

Else - (* this) は有効なオブジェクトですか?

ベースの初期化リストが完了すると、ベースのすべてのメンバー (およびベース クラス) が完全に構築されます。ただし、クラス自体は、コンストラクターが終了したときにのみ完全に構築されます。
さらに重要なことに、派生クラスのコンストラクターはまだ開始されていないため、オブジェクトはまだ派生クラスのオブジェクトではありません。

そのため、その登録関数が何をするにしても、オブジェクトの動的な型がbaseあり、そのコンストラクターがまだ終了していないことを考慮する必要があります。(安全のために、できることはオブジェクトのアドレスをどこかに保存することだけです。)

于 2010-11-24T13:53:30.747 に答える
1

参考までに、動作は C++03 の § 12.7 2-3 で指定されています。

2) クラス X のオブジェクトを参照するポインタ (左辺値) を、X の直接的または間接的な基底クラス B へのポインタ (参照) に明示的または暗黙的に変換するには、X の構築と、その直接または間接のすべての構築B から直接的または間接的に派生する間接ベースが開始され、これらのクラスの破棄が完了していない必要があります。そうでない場合、変換によって未定義の動作が発生します。

thisへのポインタDerivedです。InはBase::Base()this暗黙的に aBase*にキャストされます。これは、Derived の構築が開始され、 から派生する他のベースがないため許可されBaseます。

§ 12.7 2 続き:

オブジェクト obj の直接の非静的メンバーへのポインターを形成する (またはその値にアクセスする) には、obj の構築が開始され、その破棄が完了していない必要があります。それ以外の場合、ポインター値の計算 (またはメンバー値へのアクセス) は完了していません未定義の動作が発生します。

最後に、§ 12.7 3 も重要です。

3) 仮想関数 (10.3) を含むメンバー関数は、構築または破棄 (12.6.2) 中に呼び出すことができます。仮想関数がコンストラクター ( mem-initializerを含む) から直接または間接的に呼び出された場合データ メンバの場合) またはデストラクタから、および呼び出しが適用されるオブジェクトが構築中または破棄中のオブジェクトである場合、呼び出される関数は、コンストラクタまたはデストラクタ自身のクラスまたはそのベースの 1 つで定義されている関数ですが、コンストラクタまたはデストラクタのクラスから派生したクラスでそれをオーバーライドする関数、または最も派生したオブジェクトの他の基本クラスの 1 つでそれをオーバーライドする関数 (1.8)。仮想関数呼び出しが明示的なクラス メンバ アクセス (5.2.5) を使用し、object-expression が構築中または破棄中のオブジェクトを参照しているが、その型がコンストラクタまたはデストラクタ自身のクラスでもその基底の 1 つでもない場合、呼び出しは未定義です。

これらの 2 つの句は、一貫性のない状態にある可能性がありますが、コンストラクターが開始されると、のインスタンスがDerived完全に機能することを意味します。BaseBase

于 2010-12-05T06:04:34.977 に答える