struct CA{
CA(){ CA::foo(); } // calling foo() without CA is wrong
virtual int foo(){}
};
struct CB {
CB(){ CB::foo(); } // calling foo() without CB is wrong
virtual int foo();
};
プログラム内で非純粋仮想関数を定義する必要があり、CB::foo
どこかに定義が必要であり、クラス定義内で定義されているかどうかは実際には問題ではないことを考えると、2つのクラスの間に顕著な違いは見られません。何処か別の場所。
foo()
どちらの場合も(明示的な修飾なしで)への呼び出しは間違っています。foo()
とを使用する場合の違いは、最初のケースでは最終的に関数の最終オーバーライドType::foo()
を呼び出す動的ディスパッチを使用しているのに対し、修飾されたケース ( ) では追加の修飾によって動的ディスパッチが禁止されることです。Type::foo
この時点でに注意することが重要です。オブジェクトの動的な型は、型階層の構築中に変更されます。基本コンストラクターを評価している間、動的型はbase
であるため、最終的なオーバーライドはそのクラスからのみ取得できます。基本コンストラクターが完了すると、動的型は階層内の次の型に変更され、最終的なオーバーライドはこれら 2 つの型から選択できます。
struct base {
base() { foo() };
virtual void foo() { std::cout << "base\n"; }
};
struct d1 : base {
d1() : base() { foo() };
};
struct d2 : d1 {
d2() : d1() { foo() };
virtual void foo() { std::cout << "d2\n"; }
};
型のオブジェクトの構築は、サブオブジェクトd2
を構築することから始まります。そこでの呼び出しは、現時点では型のみを考慮して出力する最終的なオーバーライドにディスパッチされます。次に、コンストラクターが実行され、このレベルで最終的なオーバーライドを選択する呼び出しが行われます。その後、コンストラクターが評価されます。この時点で、最終的なオーバーライダーが出力され、次の結果が得られます。base
foo()
base
"base"
d1
foo()
base::foo()
d2
d2::foo()
"d2"
base
base
d2
私たちが作成している完全なオブジェクトだけがタイプであると考えたとしてもd2
、それは一時的にbase
オブジェクトとして動作し、次にオブジェクトとして動作し、コンストラクターが実行を開始しd1
たときにのみ、オブジェクトとして動作し始め、 を呼び出すことに注意してください。これは多くの人にとって混乱を招くと考えられています。d2
d2
d2
各レベルでのオブジェクトの動的な型は、評価されるコンストラクターの型とまったく同じであるため、最終的なオーバーライドは常にその型にディスパッチされることに注意してください。余分な資格を追加しても、対処する場合を除いて大きな違いはありません...
純粋仮想関数
純粋仮想関数は定義を持つことができます。純粋修飾子は、派生型がその仮想関数の定義を提供する必要があることを意味し、動的ディスパッチが実行されるときに純粋仮想関数 (定義されている場合) が呼び出されないことも意味します。その特定のケースでは、動的ディスパッチを無効にする追加の修飾を使用して、その特定の実装を呼び出すことができます。
struct base {
base() { base::foo(); } // [*]
virtual void foo() = 0;
};
void base::foo() { std::cout << "base\n"; }
struct derived : base {
derived() : base() { foo(); base::foo(); }
virtual void foo() { std::cout << "derived\n"; }
};
これは、評価されるコンストラクターが純粋な仮想であり、最終的な overriderfoo
がない場合など、 inへの非修飾呼び出しの形式が正しくない唯一のケースです。一方、修飾を追加すると、動的ディスパッチが無効になり、上記のコードがコンパイルおよび実行されます。また、コンストラクターでは、追加の修飾を使用して、このレベルで最終的なオーバーライドではない可能性がある関数の特定の定義を選択できることに注意してください。上記のコードは次を出力します。[*]
foo
derived
base::foo
base
derived
base