1

構築および破棄中に仮想メソッドを呼び出すと、コンパイラエラーが発生しますか?危険なことだと聞きました。

Class Base仮想メソッドを定義するがあればfoo()、の解決はのfoo()すべてのサブクラスで動的であることを知っていBaseます。したがって、サブクラスDerivedがオーバーライドするとfoo()、thenDerived::foo()が呼び出されます。では、構築/破棄中に仮想メソッドを呼び出すと、コンパイラが混乱するのはなぜですか?

コンストラクターから呼び出すことと、コンストラクターの外部で呼び出すことの違いは何ですか?

4

2 に答える 2

6

の構築中Base()、派生クラスはまだ初期化されておらず、実際にはまだ存在していません。仮想メソッドを呼び出すと、呼び出しはに移動しBase::foo()ます。これは必ずしも間違っているわけではありませんが、多くの場合予期しないものであるため、一般的に禁止されています。

同様に、破棄中、Derivedは~Base()呼び出される前に破棄されるため、仮想メソッド呼び出しはになりますがBase::foo()、これも予期しないことがよくあります。

于 2012-11-19T18:37:17.577 に答える
4

この例を実行してみてください:

struct base {
   virtual int f() const { return 0; }
   base() { std::cout << f() << "\n"; }
   ~base() { std::cout << f() << "\n"; }
};
struct derived : base {
   const int value;
   derived(int v) : value(v) {}
   virtual int f() const { return value; }
};
derived d(100);       // What should this print?

問題は、基本型のコンストラクターが実行されているとき、オブジェクトの型はまだbaseであり、ではないということderivedです。ディスパッチはfinal-overriderにヒットしません(ユーザーの観点からは、derivedオブジェクトを作成しただけです)。同じことが破壊でも起こります。

于 2012-11-19T18:39:35.267 に答える