如果函数参数类型是ABC,为什么不能按值传递?

Why cant pass-by-value work if the function parameter type is an ABC?

本文关键字:为什么 不能 按值传递 ABC 函数 参数 类型 如果      更新时间:2023-10-16

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

如果你要发送参数的函数的形参类型是抽象基类(ABC),

按值传递不起作用。您必须通过引用传递参数(这将是一个派生类)。

我的问题是:

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

是否有一些"内部"的c++要求它是一个引用?

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

这是因为对象切片:通过value接收的抽象类将接收到你传递的对象的副本;因此,派生数据成员将从对象中剥离,使对象不可用。

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

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

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

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

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

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

foo(v);

所发生的是,参数t表示一个新的对象,它是从参数v复制初始化的,就好像你在做:

T t = v;

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

是否有一些"内部"的c++要求它是一个引用?

差不多。c++中的动态多态性只能通过引用和指针工作。当您尝试将派生类的对象赋值给基类的对象时,您得到的是对象切片

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

一般来说,你希望通过引用或指针传递,这样你就不会对对象进行切片。这里有一个很好的答案:什么是对象切片?

当你按值接收一个对象时,它的动态("真实"类型)类型就是它的静态类型。动态类型为抽象类型的变量是不可能的。