通过值将子类对象传递给接受超类对象的函数是定义良好的行为吗
Is it well-defined behavior to pass a subclass object by value to a function taking a superclass object?
我已经研究了相关的问题,比如关于这个主题的here和here,它们都描述了对象切片,但没有一个涉及它是否是安全、可靠和可预测。
标准或编译器是否保证,如果我按值将子类对象传递给想要超类的方法,则被切片的部分恰好是子类的成员,并且我将能够使用切片的超类对象,而不必担心未定义的行为?
是的,它是安全、可靠和可预测的,因为它是由标准定义的(它只会从派生类对象复制构造基类对象)。
但不,它是不安全的,不应该依赖它,而且通常被视为不可预测的,因为你的读者不会知道发生了什么。当其他人稍后试图修改你的代码时(包括你未来的自己),这会引发很多错误。它基本上是一个no,与goto
语句非常相似,后者定义良好、可靠且可预测。
当他们说"部件被切除"时,并不意味着这些部件以某种方式"消失":所有这些部件都意味着这些部分不会复制到为相应参数提供给函数的对象中。从这个意义上说,对象切片并不危险或定义不周。
那里发生的事情相当简单:为了构造通过值传递的参数的值,用于实际参数的派生类的对象被提供给基类的构造函数以进行复制。一旦复制构造函数完成了它的工作,就有了基类的对象。
在这一点上,您已经拥有了一个功能齐全的基类对象。编译器保护您不接受按值具有纯虚拟成员的类,因此您将无法将对象切片为缺少纯虚拟函数的实例。
一个更重要的问题是,您是否希望切片行为隐式发生:编译器在这里所做的一切都是您在代码中无法做到的:
void foo(bar b) {
... // Payload logic
}
提供与相同的功能
void foo(const bar &r) {
bar b(r);
... // Payload logic
}
对于第一个片段,很容易忽略一个事实,即在类型的名称后面缺少一个&符号,这会导致读者认为多态行为得到了保留,而实际上它已经丢失了。第二个片段对维护代码的人来说更容易理解,因为它明确地生成了一个副本。
- 如何创建对象函数指针C++映射?
- 为什么我可以改变常量对象中的成员变量,这是返回常量对象函数的结果?
- 如何将对象函数的实例传递给另一个函数
- 调用模板函数的问题"No matching function for call"参数:迭代器、对象函数
- makefile对我的名称空间对象/函数/构造函数的不确定引用
- 将对象函数转换为函数指针
- 非对象函数/类函数C++
- 线程对象函数 C++
- C 将成员对象函数分配给类成员功能
- 使用基本指针调用派生对象函数
- 可以(通过编译器)使用多少个线程来初始化全局对象(函数main之前)
- C++类对象函数
- 对对象::函数的未定义引用
- 无法弄清楚将多个对象函数作为单独的线程调用的语法
- 在提升作用域出口中调用对象函数
- 使用基指针来使用派生对象函数
- 在for_each lambda 中调用对象函数
- C++:: 模板函数 - 从对象函数获取对象的地址
- Qt5 未解析的外部静态元对象函数
- 通过变量使用对象和对象函数