私がこれまでに学んだことから、ポリモーフィズムには、コンパイル時と実行時の 2 種類があります。コンパイル時には、ポリモーフィングされた関数または演算子はコンパイラによって解決されますが、実行時には実行時に解決されます。コンパイル時ポリモーフィズムの例には、関数と演算子のオーバーロードが含まれ、実行時ポリモーフィズムには、関数のオーバーライドと仮想関数が含まれます。また、アーリー バインディングやレイト バインディングのようなケースもありますが、後で説明します。次のコードを検討してください。
class base {
public:
void Print() {
std::cout << "This is parent class\n";
}
};
class derived : public base {
public:
void Print() {
std::cout << "This is derived class\n";
}
};
私がこれを行う場合:
base b1;
b1.Print();
derived d1;
d1.Print();
結果は明らかです。
This is parent class
This is derived class
本当の問題は、基本クラスへのポインターを使用してこれらの関数を操作するときに始まります。
base b1;
derived d1;
base* pb = &b1;
base* pb2 = &d1;
pb->Print();
pb2->Print();
出力は次のようになります。
This is parent class
This is parent class
これはアーリー バインディングによるもので、コンパイラは、関数が処理するオブジェクトの型ではなく、関数を呼び出しているオブジェクトの型をチェックします。そして、明らかにそれはコンパイル時に行われます。基本クラスの関数定義でキーワードを使用するとvirtual
、処理するオブジェクトのタイプに基づいてランタイムの関数定義を保存する遅延バインディングが原因で、手間をかけずに上記を簡単に実行できます。これはランタイム ポリモーフィズムの例です。
時間がかかりすぎて申し訳ありません。私の質問は、これがランタイム ポリモーフィズムを達成できる唯一の方法ですか? また、関数のオーバーライドがランタイム ポリモーフィズムである場合、前の例 (つまり、アーリー バインディングを使用したもの) も関数のオーバーライドを行っているため、ランタイム ポリモーフィズムである必要があります。