あなたが3台の異なる車を持っているとしましょう。そして、それらを駆動するさまざまなメカニズムがあります。ドライバーは、基礎となるエンジンについて知る必要はなく、車を運転する方法のプロトコルのみを知る必要があります。つまり、このペダルを踏んで加速し、そのペダルを踏んでブレーキをかけるなどです。
ドライバーの観点からは、ホンダ、フォード、ビュイックのいずれであっても問題ありません。彼から見ればただの車だ。同様に、車が駐車されている小屋がある場合、それらを car shed と呼びます。それは車を収容し、それぞれが何であるかについて気にしません。そう
std::vector<Car*> v;
v.push_back(new Ferrari());
v.push_back(new Honda());
v.push_back(new Ford());
クラスのオブジェクトを作成することで同じ作業ができるのに、なぜ参照/ポインターを使用する必要があるのですか?
ポインターまたは参照がなければ、共通性があっても特定の意味で異なるオブジェクトのコレクションを作成することはできません。これは、Java、C# などの一部の厳密な OOP 言語では、すべてのオブジェクトを という基本クラスから派生させることで回避されObject
ます。C++ はマルチパラダイム言語であり、プログラマーは自分のプロジェクトに適した決定を自由に行うことができます。C++ でこれを行う方法は、基本クラスのポインターを使用することです。このイディオムは、ランタイム ポリモーフィズムと呼ばれます。
for (const auto &this_car : v)
this_car->drive();
ここでは、実際のメーカーに関係なく、基本クラスが型の一部であるv
限り、ベクターは車を保持できます。car
同様に、drive
make ごとに異なりますが、それを呼び出す関数がそれを知っている必要はありません。
編集:
この投稿が実際には質問に答えていないことを指摘してくれた nijansen に感謝します: なぜポインターまたは参照 (動的型) がランタイム ポリモーフィズムに必要なのですか? 彼らはそれを達成するために使用したと言っているだけで、通常の(静的型)変数を使用できない理由は説明していません。
C++ は、オブジェクトの型が手元にあるだけで、コンパイル時に完全に認識される場合と認識されない場合があるように設計されています。はタイプであることがCircle c;
わかっています。一方では、どのオブジェクトが指しているのか本当にわかりません。自身の型は ですが、指しているオブジェクトの具象型は不明です。私たちが知っているのは、 から派生した何らかのオブジェクトを指していることだけです。動的または自動メモリ割り当てと混同しないでください。これは、自動変数でも同じです。ここでも孤立して、コンパイラーは、オブジェクトがどの具体的な型であるかを認識していません。c
Circle
Shape *p = make_shape();
p
p
Shape*
Shape
Shape *p = &c;
p
p
p
静的(非ポインター、非参照)型として記述した場合、Shape p = make_shape();
またはスライスShape p = c;
で実際に起こること、つまり具象型になり、ポインターではないため、オブジェクトの(形状)部分をそれにコピーします。ほとんどの場合望ましくありません。p
Shape
Circle
c
基礎となる型を知らずに、適切な具体的な型の関数をどのように呼び出すのでしょうか? C++ は、ジョブを実行するための仮想関数を提供します。これが、ランタイム ポリモーフィズムが常に C++ の仮想メソッドで説明される理由です。Java や C# などの言語では、すべてのメソッドが仮想であり、すべてのオブジェクト型が参照/ポインターです。あなたの質問への答えは、ランタイムポリモーフィズムのために参照/ポインター変数が必要になるように言語が設計されているということです。