对象切片发生于派生类对象赋值给基类对象时,仅拷贝基类子对象,丢失派生类成员及虚表信息;指针/引用不切片因不复制内存,而值传递或容器存储会静默切片导致多态失效。

会发生对象切片(object slicing):基类对象只保留派生类中继承自基类的那部分成员,派生类新增的成员和虚表信息全部丢失。
赋值后基类对象无法访问派生类成员
派生类对象赋给基类对象是值拷贝,不是引用或指针绑定。编译器只复制基类子对象的内存布局,其余一概忽略。
-
Base b = derived;这行代码触发的是Base的拷贝构造函数(或赋值运算符),而非任何多态机制 -
b是一个独立的、纯Base类型的对象,derived中的derived_var、derived_func()等完全不可见 - 即使
Base::func()是虚函数,b.func()也只会调用Base版本——因为b的虚表指针指向Base的虚表
为什么指针/引用不会切片,而对象会
关键区别在于是否发生内存拷贝:
-
Base* p = &derived;:p指向原始derived对象的起始地址(即其基类子对象位置),虚表指针仍有效 -
Base& r = derived;:r是derived的别名,不新建对象,类型信息完整保留 -
Base b = derived;:分配新内存,仅按Base的大小和布局拷贝字节,derived的后续内存被跳过
常见误用场景与错误现象
最典型的坑是把多态逻辑写成值传递,结果“虚函数失效”:
立即学习“C++免费学习笔记(深入)”;
- 函数形参写成
void process(Base obj),传入Derived对象 → 传入瞬间就切片,obj是纯Base - 容器存
std::vector<base>,然后push_back(derived)→ 每次都切片,容器里全是“残缺”的Base实例 - 错误地认为
Base b = derived;后还能通过b调用派生类特有接口,编译直接报错:b.derived_var未声明
切片本身不报错,但它是静默发生的——你得不到警告,却在运行时发现行为和预期完全不同。真正要警惕的,从来不是编译失败,而是“看起来能跑,结果不对”。


















