动态绑定与虚函数:存储Base类对象的vector为何无法调用正确成员函数
问题原因:对象切片(Object Slicing)
你遇到的是C++中非常典型的对象切片现象,核心原因是std::vector<Base>存储的是基类对象实例,而非指针或引用,不满足多态的触发条件。
具体原理
C++的多态(虚函数动态派发)生效有两个必要前提:
- 通过指针或引用调用虚函数
- 指针/引用指向的是完整的派生类实例,对象本身的虚表指针是派生类对应的版本
std::vector<Base>的每个元素内存大小固定为Base类的大小,当你将Derived类型的d存入vector时,会自动调用Base的拷贝构造函数,只拷贝d中属于Base类的成员部分,Derived类特有的成员、以及Derived类的虚表指针信息都会被截断丢弃,最终存入vector的本质就是一个纯Base类对象,自然只会调用Base的print函数。
对比你之前写的Base* p2 = &d的场景:指针本身只占固定大小的内存,指向的是完整的Derived实例内存,对象的虚表指针还是Derived类的版本,所以调用虚函数可以触发多态。
修复方案
如果要在容器中使用多态,需要存储基类的指针或智能指针:
方案1:存储裸指针
std::vector<Base*> v {&b, &d}; v[1]->print(); // 输出Derived
注意需要手动保证容器内指针指向的对象生命周期长于容器,避免出现野指针。
方案2:存储智能指针(更安全,无需手动管理内存)
#include <memory> // ... std::vector<std::unique_ptr<Base>> v; v.push_back(std::make_unique<Base>()); v.push_back(std::make_unique<Derived>()); v[1]->print(); // 输出Derived
内容的提问来源于stack exchange,提问作者user3306199
相关产品推荐
相关产品推荐

