1. ホーム
  2. c++

なぜランタイムポリモーフィズムはコンパイル時に解決できないのか?

2023-09-15 11:24:29

疑問点

考えてみてください。

#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;
}

なぜこのコードはランタイムポリモーフィズムを引き起こし、なぜコンパイル時に解決できないのでしょうか?

どのように解決するのですか?

なぜなら、一般的な場合、それは 不可能 であり、実行時にどのような型になるかを決定することはできません。 あなたの例はコンパイル時に解決できますが (@Quentin による回答を参照)、そうでないケースも構築できます、たとえば。

Base *bp;
if (rand() % 10 < 5)
    bp = new Derived;
else
    bp = new Base;
bp->show(); // only known at run time

EDIT: @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 のインスタンスを指しています。 BaseA で、"q.cpp" のポイント。 bp にある他の何かに A . そして、"q.cpp"でそう判断された場合。 bp のインスタンスを指していない。 BaseA であれば、"q.cpp" のポイントは bp のインスタンスに BaseA . これは矛盾しています。 つまり、最初の仮定は間違っているのです。 そこで bp_points_to_base は書けません。 一般的な場合 .