0

多くの情報源、書籍などでは、「子クラスのコンストラクターで this->virtualFunction を呼び出さないでください」と書かれており、一部の情報源では、それを行ってはならない理由が説明されています。構築の時点では、クラスはまったく作成されていないためです。したがって、子コンストラクターから呼び出される仮想関数は、基本クラスの関数になります。これは、子コンストラクタ本体で、そのクラスの VPTR がベース VTABLE を指していることを意味します。

だから私の質問は、
子クラスの VPTR が仮想テーブルでアドレス指定するためにオーバーライドされるオブジェクト構築の瞬間は何ですか? 自動生成されたコードの一部は、コンストラクター本体の最後またはコンストラクター本体が実行された後にそれを行うと思います。

2 番目の質問は、
なぜ VPTR が構築の最後に上書きされるのですか? 多分それにはいくつかの重要な理由がありますか?コンストラクタ本体の開始時または基本クラスの構築後に VPTR をオーバーライドできないのはなぜですか?

Child::Child() :
Base()
//<----- Why not here?
//members initialization
{
//<----- Why not here?
//code
}
4

2 に答える 2

1

多くの情報源、書籍などで「子クラスのコンストラクターで this->virtualFunction を呼び出さないでください」と書かれています。

私はそれを疑います。基本クラスのバージョンではなく、最終的なオーバーライドを呼び出すと予想される場合の混乱を避けるために、基本クラスのコンストラクターから仮想関数を呼び出さないことをお勧めします。また、それらが純粋な仮想である場合は、基本クラスからそれらを呼び出してはなりません-未定義の動作が発生します。

派生クラス コンストラクター内では、それらは明確に定義されており、期待どおりの動作をします。

したがって、子コンストラクターから呼び出される仮想関数は、基本クラスの関数になります。

いいえ、子のコンストラクタ本体の間、動的型はChildであり、仮想関数呼び出しはChildオーバーライドを使用します。

子クラスの VPTR が仮想テーブルのアドレスにオーバーライドされるオブジェクト構築の瞬間はいつですか?

すべての基本クラスのコンストラクターが完了した後、子クラスのメンバーが初期化される前。Child仮想関数を含むメンバー関数は、メンバー初期化子 (基底クラスの初期化子ではない) またはコンストラクタ本体から呼び出すことができます。

初期化されていないメンバーにアクセスする可能性があるため、メンバー初期化子からの呼び出しには注意が必要です。ただし、コンストラクター本体内では、すべての基本オブジェクトとメンバーが初期化されるため、非常に安全です。

構築の最後に VPTR が上書きされるのはなぜですか?

そうではありません。で示した最初のポイントで発生します<----- Why not here?

于 2014-12-04T14:42:31.737 に答える