考慮する:
#include<iostream>
using namespace std;
class Base
{
public:
virtual void show() { cout<<" In Base \n"; }
};
class Derived: public Base
{
public:
void show() { cout<<"In Derived \n"; }
};
int main(void)
{
Base *bp = new Derived;
bp->show(); // RUN-TIME POLYMORPHISM
return 0;
}
このコードはなぜ実行時ポリモーフィズムを引き起こし、コンパイル時に解決できないのでしょうか?
ベストアンサー1
一般的には、不可能コンパイル時に、実行時にどの型になるかを決定します。あなたの例はコンパイル時に解決できます (@Quentin の回答を参照) が、次のように、コンパイル時に解決できないケースも構築できます。
Base *bp;
if (rand() % 10 < 5)
bp = new Derived;
else
bp = new Base;
bp->show(); // only known at run time
編集: @nwp のおかげで、もっと良いケースが見つかりました。次のようなものです:
Base *bp;
char c;
std::cin >> c;
if (c == 'd')
bp = new Derived;
else
bp = new Base;
bp->show(); // only known at run time
また、チューリングの証明、次のことが示される。一般的なケースではC++ コンパイラが実行時に基本クラス ポインタが何を指しているかを知ることは数学的に不可能です。
C++ コンパイラのような関数があると仮定します。
bool bp_points_to_base(const string& program_file);
それは入力として次program_file
の名前を受け取ります:どれでもC++ソースコードテキストファイル。ポインタbp
(OPのように)がそのvirtual
メンバー関数を呼び出しますshow()
。そして、一般的なケースでは(メンバー関数が を通じて最初に呼び出されるシーケンス ポイントでA
) virtual
:show()
ポインターbp
がbp
のインスタンスを指しているBase
かどうか。
C++ プログラム「q.cpp」の次の部分を考えてみます。
Base *bp;
if (bp_points_to_base("q.cpp")) // invokes bp_points_to_base on itself
bp = new Derived;
else
bp = new Base;
bp->show(); // sequence point A
ここで、 がbp_points_to_base
「q.cpp」で が のインスタンスを指していると判定した場合、はbp
で別のものを指します。また、 が「q.cpp」でが のインスタンスを指していないと判定した場合、はのインスタンスを指します。これは矛盾です。したがって、最初の仮定は正しくありません。したがって、 は次のように記述できません。Base
A
bp
A
bp
Base
A
bp
Base
A
bp_points_to_base
一般的なケース。