避免对象切片
10.6.3 ID_objectSlicing
将派生类对象复制为基类对象的行为称为“对象切片(object slicing)”,基类对象不再持有派生类的属性,不再遵循多态机制,意味着某种精度上的损失,往往会造成意料之外的错误。
示例:
struct A { .... };
struct B: A { .... };
void foo(A);
A a;
B b;
a = b; // Slicing
foo(b); // Slicing
vector<A> v{b}; // Slicing
v.push_back(b); // Slicing
尤其是函数传参或容器收纳对象时发生切片,会引起相当大的困惑,明明传入的是派生类对象,但虚函数都不生效了,所以要求多态性的接口或容器均应使用指针或引用。
在少数情况下,对象切片可能也有其逻辑意义,但不建议“隐式切片”,应定义特定名称的函数标明这是一种特殊处理,如:
A a;
B b;
a = b; // Bad, implicit slicing
a = to_base_object(b); // OK
其中 to_base_object 是一个返回基类对象的函数,表示有意为之。