1

我正在读一本书,上面写着:

如果您向其发送参数的函数的参数类型是抽象基类 (ABC),则按值传递不起作用。您必须通过引用传递参数(这将是一个派生类)。

我的问题是:

为什么不能按值传递派生类参数?

C++ 是否有“内部”的东西需要它作为参考?

这与动态绑定的工作方式有关吗?

4

4 回答 4

6

这是因为对象切片:值接收的抽象类将接收您传递的对象的副本;因此,派生的数据成员将被从中分割出来,使对象不可用。

当您通过引用传递时,您传递的是现有对象的地址,该对象是派​​生类的成员,包括其所有数据成员。这不是 C++ 特有的——这是一般按值传递的属性。

动态绑定以不允许切片实例接收调用的方式实现,就好像它是一个完整实例一样。调整vtable指针以分派对抽象基类的成员函数的调用。

于 2013-06-01T20:38:44.897 回答
5

为什么不能按值传递派生类参数?

简单地说,如果你有一个看起来像这样的函数:

void foo(T t); // Takes a T by value

你这样称呼它(不管v是什么):

foo(v);

发生的情况是参数t表示一个从参数复制初始化的对象v,就像您正在做的那样:

T t = v;

现在如果T是抽象的,上面是非法的,因为你不能实例化一个抽象类(根据定义)。因此,参数 offoo()不能从其参数复制初始化。

C++ 是否有“内部”的东西需要它作为参考?

类似的东西。C++ 中的动态多态性只能通过引用和指针工作。当您尝试将派生类的对象分配给基类的对象时,您得到的是对象切片

于 2013-06-01T20:39:11.897 回答
3

您可以按值传递派生类。您不能通过值将抽象基类作为参数传递,因为无法实例化抽象类。

通常,您希望通过引用或指针传递,以免对对象进行切片。这里有一个很好的答案:什么是对象切片?

于 2013-06-01T20:39:04.630 回答
0

当您按值接收对象时,它的动态(它的“真实”类型)类型就是它的静态类型。不可能有一个动态类型是抽象类型的变量。无论您如何构建它。

于 2013-06-01T20:42:11.407 回答