如何在STL list中使用多态?虚函数调用结果异常问题求解
问题原因
这个现象是**对象切片(Object Slicing)**导致的:
- 你定义的
list<A>是直接存储A类的实例对象,当执行my.push_back(*b)时,会将B对象中属于基类A的成员拷贝到list的新元素中,B类独有的部分会被直接截断,最终list里存储的只是一个普通的A类实例,其虚函数表指针指向A类的虚表,所以调用print()时会执行A类的实现,输出no。 - 而
b是B类型的指针,指向堆上完整的B类实例,虚表指针指向B类的虚表,所以调用print()会触发多态,执行B类重写后的实现,输出0。
修改方案
要触发多态,STL容器需要存储基类的指针(推荐用智能指针避免内存泄漏),不要直接存储基类实例,修改后的代码如下:
#include <iostream> #include <list> #include <memory> // 引入智能指针头文件 using namespace std; class A{ public: A(): data_(0){} // 基类有虚函数时要添加虚析构函数,避免子类对象通过基类指针释放时内存泄漏 virtual ~A() = default; virtual void print(){ cout << "no" << endl; } protected: int data_; }; class B : public A{ public: B(): A(){} void print() override{ cout << data_ << endl; } }; // 改为存储基类的智能指针 list<unique_ptr<A>> my; int main() { unique_ptr<B> b = make_unique<B>(); b->print(); my.push_back(move(b)); // 转移所有权到list中 for (auto& i : my){ i->print(); } return 0; }
如果选择手动管理内存,也可以将list改为存储普通A*指针,但需要在程序结束前遍历list手动delete每个元素,避免出现内存泄漏。
内容的提问来源于stack exchange,提问作者Atoro
相关产品推荐
相关产品推荐

