7

この質問では、コンパイラがnewをサポートしておらず、配置newがサポートされていない場合のファクトリメソッドの作成について説明します。明らかに、新しい配置によって行われるすべての必要なステップが何らかの方法で再現される場合、malloc()を使用していくつかの適切なソリューションを作成できます。

新しい配置は何をしますか-私はリストに載せて、何も見逃さないことを望んでいます-以下を除いて?

  • すべての基本クラスのコンストラクターを再帰的に呼び出す
  • すべてのメンバー変数に対してコンストラクターと初期化子(存在する場合)を呼び出す
  • それに応じてvtableポインタを設定します。

他にどのようなアクションがありますか?

4

3 に答える 3

6

配置は、メモリの割り当てを除いてnew、通常のすべてのことを行います。new

いくつかの小さな説明を加えて、何が起こるかを本質的に釘付けにしたと思います:

  • 明らかに、クラス自体のコンストラクターも呼び出されます
  • vtable ポインターは、個別にではなく、コンストラクター呼び出しの一部として初期化されます。これが意味することは、部分的に構築されたオブジェクト (コンストラクターでスローされた例外を考えてください) は、構築が進行した時点まで vtable が設定されているということです。

構築/初期化の順序は次のとおりです。

  1. 宣言順の仮想基底クラス
  2. 宣言順の非仮想基底クラス
  3. 宣言順のクラスメンバー
  4. クラスコンストラクター自体
于 2009-06-23T09:49:00.447 に答える
4

それに応じて vtable ポインタを設定する

この部分はほぼ完全に実装定義です。コンパイラが vtables を使用していない可能性があります。複数の vtable ポインター、または vtable ではないものへの 1 つ以上のポインターが存在する場合があります。仮想基本クラスと同様に、多重継承は常に楽しいものです。このメタデータは、別のオブジェクトにコピーできることが保証されていないmemcpyため、ポインターは絶対的である必要はありません。オブジェクトポインター自体に相対的なオフセットがそこにある可能性があります。

IIRC では、基本クラス コンストラクターが呼び出され、vtable ポインターが基本クラスに設定され、最初の派生クラス コンストラクターが呼び出されるなどの処理が一般的に行われます。これは、次の場合に何が起こるかに関する仕様の要件を満たすためです。仮想関数はコンストラクターで呼び出されます。私が覚えている限り、標準には「アクションのリスト」はなく、定義された初期化順序だけです。

そのため、実装が何をするかを一般化することはできません。特に、C++ 標準の実装ではないためです。おそらくターゲットプラットフォームで使用すべきではないと考えているため、おそらく正当な理由で「新しい」を除外して手抜きをした場合、それが無視する言語の他のルールを誰が知っていますか。malloc と少しのポインタープッシュで「new」をモックアップすることが可能である場合、一体なぜコンパイラーは単に new を実装しないのでしょうか? コンパイラの専門家が回答できるように、特定のコンパイラとプラットフォームでタグ付けされた質問をする必要があると思います。

于 2009-06-23T09:56:23.910 に答える