友人の1人が、「C ++でランタイムポリモーフィズムを実現するにはどうすればよいですか?」と尋ねました。私は「継承によって」と答えました。彼は「いいえ、仮想関数を使用することによってのみ達成できます」と述べました。
まず、ポリモーフィズムという用語はあいまいです。一般的なコンピューティングサイエンスの意味では、コンパイル時か実行時かに関係なく、タイプ固有のコードを暗黙的に呼び出す機能を指します。C ++標準では、非常に狭く定義されており、仮想ディスパッチです(これは標準の浸透です)。明らかに、友人の質問が意味のあるものになるためには、彼がC ++でどのように達成されるかを尋ねているので、彼の視点はC++の外部からでなければなりません-コンピューティングサイエンスの用語のより大きな文脈で。
確かに、仮想関数/ディスパッチは答えですが、それが唯一の答えですか...?
これに答えるには、実行時のポリモーフィックとしてどのような動作が適格であるかを明確に理解することが役立ちます。検討:
void f(X& x)
{
// the only situation where C++ doesn't know the run-time type of a variable is
// where it's an instance of a class/struct accepted by reference or pointer
...some operation involving "x"...
}
実行時タイプの「x」に特に関連する理由で、「x」を含む操作に対して異なるマシンコードが呼び出される可能性のあるメカニズムは、実行時ポリモーフィックにかなり近づいていますが、最後の問題が1つあります。 :その分岐は言語によって暗黙的に決定されたのですか、それともプログラマーによって明示的に配置されたのですか?
仮想ディスパッチの場合、コンパイラは、タイプに適したコードに分岐する仮想ディスパッチテーブルとルックアップを作成することを暗黙的に認識しています。
ただし、以前にタイプ固有のコードをアドレス指定するように設定された関数ポインター、またはタイプ固有のを制御するために使用されるタイプ固有の数値または列挙switch
型があるとしcase
ます。これらは機能的に実行時仮想ディスパッチと同じ動作を実現しますが、セットアップは開発者が明示的に行う必要があり、決定が純粋に実行時型で行われることを確認するコンパイラの強制はありません。彼らが資格を得るかどうかは議論の余地があります。C ++には仮想ディスパッチの完全な暗黙のメカニズムがあり、C ++標準では、特に仮想ディスパッチに関連する定義が狭められているため、ほとんどのC++プログラマーは「いいえ」と言うでしょう。
しかし、Cの世界では、sayqsort
またはbsearch
(関数ポインター引数を介した実行時ディスパッチを使用して任意の型を処理する2つの標準libC関数)を実行時ポリモーフィックとして説明すると、すぐに理解できる場合があります...ただし、一般的な実装。
それでも、実行時のポリモーフィズムの機能定義が記載されたコンピューティングサイエンスの教科書は間違いなく何百もあり、関数ポインターまたは他のプログラマーが初期化したメタデータを使用してディスパッチすることで、かなりの割合を満たしているに違いありません。したがって、明確な答えが1つしかないことを主張しすぎるのは無意味です。
私の質問は:-
1)ランタイムポリモーフィズムは仮想関数でのみ実現されますか?
上記のように、私はC ++のコンテキストでは「はい」に傾倒しますが、それは(際限なく)議論の余地があります。
2)上記の例には、実行時のポリモーフィズムまたはコンパイル時間がありますか?
どちらでもありません...タイプに基づいて選択する2つの関数さえありません-func()
タイプがであるという期待を与えられてコンパイラによって選択された:に対して常に同じマシンコードを実行していますA
。
3)次のコードがある場合:-
void func2(A& myA)
{
cout << myA.i << endl;
// dynamic/static cast myA to myB
cout<<myB.j << endl;
}
どんなポリモーフィズムですか?それともポリモーフィズムですか?
タイプに基づく分岐がないため、ポリモーフィックではありません。動的キャストは、実行時型myAのコンパイラー入力型メタデータを参照できます。これを使用して、へのアクセスのみを条件付きで呼び出す場合は、 -myB.j
でない限り未定義の動作になります-に戻ります。手動で、明示的に開発者が調整したタイプ固有の動作、およびそれが「ポリモーフィズム」として適格かどうかについては、上記で説明しました。myA
B