C++多态:基类vector存子类对象调用虚函数为何输出基类结果?
C++多态调用不符合预期问题排查
问题复现
学习C++多态特性时编写如下测试代码,预期运行输出结果为5,实际运行输出为3,虚函数未按预期调用子类重写的实现:
#include <iostream> #include <vector> using namespace std; class A { public: int x = 3; virtual void print() { cout << 3 << endl; } }; class B : public A { public: int x = 5; void print() { cout << 5 << endl; } }; int main() { B b; A a; vector<A> name1; name1.push_back(b); name1[0].print(); cout<< name1[0].x << endl; return 0; }
问题原因
向元素类型为基类A的vector中压入子类B的对象时,会发生对象切割(Object Slicing):
- 压入元素的拷贝过程仅会保留子类实例中属于基类
A的成员部分,子类B独有的成员(包括子类定义的x变量、虚函数表中对应子类重写方法的条目)会被完全截断丢弃 - 容器内存储的元素本质是独立的基类
A对象,不包含任何子类相关信息,虚函数的多态分发机制自然无法生效,调用方法、访问成员都会走基类A的逻辑。
修复方案
将vector的元素类型修改为基类指针类型,存储对象的内存地址而非直接存储对象实例,从根源上避免对象拷贝带来的切割问题:
- 容器定义修改为:
vector<A*> name1; - 压入元素时传入子类对象的地址:
name1.push_back(&b);
修改后再次运行代码,虚函数会正确触发动态绑定,调用子类B重写的print()方法,输出符合预期的5。
内容的提问来源于stack exchange,提问作者NoNToxic
相关产品推荐
相关产品推荐

