如果函数参数类型是ABC,为什么不能按值传递?
Why cant pass-by-value work if the function parameter type is an ABC?
我在读一本书,上面写着:
如果你要发送参数的函数的形参类型是抽象基类(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++中的动态多态性只能通过引用和指针工作。当您尝试将派生类的对象赋值给基类的对象时,您得到的是对象切片。
可以按值传递派生类。不能按值传递抽象基类作为参数,因为无法实例化抽象类。
一般来说,你希望通过引用或指针传递,这样你就不会对对象进行切片。这里有一个很好的答案:什么是对象切片?
当你按值接收一个对象时,它的动态("真实"类型)类型就是它的静态类型。动态类型为抽象类型的变量是不可能的。
相关文章:
- 为什么不能修改对象中的值?另外,我如何改进此链表?
- 为什么不能用常量表达式声明数组?
- 为什么不能直接引用作用域枚举类成员,而不能为无作用域枚举生成类成员?
- 为什么不能通过在错误输入后设置 std::cin.clear() 来使用 std::cin?
- 为什么不能使用带有模板的 lambda
- 为什么不能用两层列表初始值设定项初始化 2D std::array?
- 为什么不能将字符指针定义为数组?
- 为什么不能指向指针,在没有强制转换的情况下访问结构成员?
- 为什么不能提升::hana::overload_t成为类的成员
- 为什么不能使用 setData() 在 QTreeView 中设置单元格的背景颜色?
- 为什么不能在实例化对基类的引用的同时实例化指向派生类的指针?
- 为什么不能使用"( )"为类的非静态数据成员提供默认值?
- 为什么不能使用"->"C++模板类
- 为什么不能在C++中重新定义类中的类型名称?
- 为什么不能将此参数包直接解压缩到向量初始值设定项列表中?
- 为什么不能订购函数参数评估
- 为什么不能在 Visual C++ 中动态分配堆栈内存?但海湾合作委员会可以做到
- 为什么不能在STL映射中插入值
- Qtopengl,为什么不能用不同的vbo画两个立方体
- 与好友运算符接口<<:为什么不能链接?