You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 01:45:03