C++ 相談室 part5
■ このスレッドは過去ログ倉庫に格納されています
0304デフォルトの名無しさん
NGNGダウト。ANSI C++ の規格書では
12 Special member functions
12.6 Initialization
12.7 Construction and destruction
この項目 3 で明確に規定してある。
>>302
コンストラクタ中で仮想メンバ関数を呼び出した場合には、派生クラスではなく、
そのクラス、もしくは規定クラス中の最も外側で定義された仮想関数が呼ばれ
る。
class Base {
public:
virtual void foo();
Base() { foo(); } // この foo() は常に Base::foo() を呼び出す
};
class Deriv : Base {
public:
virtual void foo();
};
vtable はコンストラクタが実行される直前に初期化されます。
Deriv d;
は仮想的な C++ コードで書くと、次のような処理に展開できる。
d.vptr = Base::vptr; // まずは Base クラスの vtbl が設定される
d.Base(); // Base クラスのコンストラクタが呼ばれる
// vptr == Base::vptr なので foo() は Base::foo() を呼び出す
// ここまでで基底クラスの構築は完了、次に派生クラスの構築を行う
d.vptr = Base::vptr; // Deriv クラスの vtbl が設定される
d.Deriv(); // Deriv クラスのコンストラクタが呼ばれる
// 作成完了
d.foo(); // vptr == Deriv::vptr なので foo() は Deriv::foo() を呼び出す
// 実際には d が Deriv クラスのインスタンスであることをコン
// パイラは分かっているから、vptr を介さずに直接 Deriv::foo()
// を呼び出すコードを作成するけど。
したがって、デザインパターンの Template Method っぽい処理を行いたい場合に
は、コンストラクタは使えません。
■ このスレッドは過去ログ倉庫に格納されています