他の多くのエラーを削除した後のコードの作業サンプル。
#include<iostream>
class A
{
virtual void f()=0;
public:
void g();
};
void A::g()
{
f();
}
class B : public A
{
void f(){std::cout<<"Inside B::f";}
};
int main()
{
B b;
b.g();
return 0;
}
出力:
内部 B::f
本当の答え を得るために、実際のコードを投稿してください。
編集:
実際のコードを見せてくれたので(コンパイルエラーがありましたが、修正しました)。私はあなたの問題を理解しています。
Bを使用してクラスのオブジェクトを作成するB b;と、基本クラスのコンストラクタA::A()が呼び出され、次にメソッドが呼び出されますg()。g()は基本クラスのメソッドにすぎないため、これにより が呼び出されることに注意してくださいA::g()。これはさらに を呼び出しますf()。今、あなたの期待はこれが呼び出されるはずですB::f()が、そうではありません。
なぜ?
ルールに注意してください。
コンストラクタまたはデストラクタ内では、オブジェクトの型がthis指す型は常に、コンストラクタ/デストラクタが呼び出されている型です。
上記の規則を適用するf()と、 のコンストラクタで呼び出され、 が呼び出され、 がA呼び出さ
this->f()れA::f()ますB::f()。さらにA::f()、定義がないため(提供しなかったため)、実行時例外が発生します。
アクティブな例外なしで呼び出された終了と呼ばれる純粋な仮想メソッド。
コンパイラはこれをコンパイル時エラーとして検出できませんでしたvirtual。呼び出される関数は、this静的ではなく何を指しているかに応じて実行時に決定されるためです。コンパイラがこれを検出できる方法はありませんでした。
どうすればこの問題を克服できますか?
コンストラクターで動的ディスパッチを介して行うことはできません。
コンストラクタ/デストラクタを除く他のメソッドから呼び出した場合、期待どおりの動作を実現して期待できます。
コンストラクタとデストラクタで仮想関数を呼び出すことは避けてください。それらは、呼び出す可能性があると思われるバージョンを呼び出さないためです。