假设你有 3 辆不同的汽车。你有不同的驱动它们的机制。驾驶员不需要了解底层发动机,而只需要了解如何驾驶汽车的协议,即踩下该踏板进行加速,踩下该踏板进行制动等。
现在从驾驶员的角度来看,无论是本田、福特还是别克。在他看来,这只是一辆汽车。同样,如果你有车棚,停放汽车的地方,你就称它们为车棚。它容纳汽车,并不关心每辆汽车是什么。所以
std::vector<Car*> v;
v.push_back(new Ferrari());
v.push_back(new Honda());
v.push_back(new Ford());
当通过创建类的对象可以完成相同的工作时,为什么我们需要使用引用/指针?
如果没有指针或引用,您就无法创建具有某些共性但在某些特定意义上不同的对象集合。这在一些严格的 OOP 语言(如 Java、C# 等)中通过使所有对象都派生自一个名为Object
. C++ 是一种多范式语言,程序员可以自由地做出适合他/她的项目的决定。在 C++ 中执行此操作的一种方法是通过基类的指针。这个习语称为运行时多态性。
for (const auto &this_car : v)
this_car->drive();
在这里,无论实际品牌如何,v
只要基类car
是类型的一部分,向量就可以容纳汽车。同样,drive
每个品牌都会有所不同,但调用它的函数不需要知道这一点。
编辑:
感谢 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# 等语言中,所有方法都是虚拟的,所有对象类型都是引用/指针。在某种程度上,您的问题的答案是,该语言被设计为需要引用/指针变量来实现运行时多态性。