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

C++如何调用存储在vector中智能指针指向的子类重写方法

问题原因

你当前代码的核心问题是发生了对象切片(Object Slicing):

  • 你调用std::make_shared<Foo>(Foo1{})时,是先创建了一个Foo1临时对象,再以它为参数构造一个Foo类型的堆对象,子类独有的内容在这个过程中被完全切掉,最终vector里存储的全部都是父类Foo的实例,自然只会调用父类的Update方法。
  • 额外隐患:父类Foo没有定义虚析构函数,当智能指针释放对象时只会调用父类析构函数,子类资源会泄漏。
最优解法

直接构造对应子类类型的智能指针,利用多态的向上转型特性自动转为std::shared_ptr<Foo>存入vector即可,同时补充父类的虚析构函数。

修改后的完整代码如下:

#include <iostream>
#include <memory>
#include <vector>

class Foo
{
public:
    virtual void Update(){
        std::cout << "Update idle" << std::endl;
    }; 
    // 补充虚析构函数,避免资源泄漏
    virtual ~Foo() = default;
};

class Foo1 : public Foo
{
public:
    void Update() override
    {
        std::cout << "Update Foo1" << std::endl;
    }
};

class Foo2 : public Foo
{
public: // 调整Update权限为public,否则外部无法调用
    void Update() override
    {
        std::cout << Bar() << std::endl;
    }

private:
    std::string Bar(){
        return "Update Foo2";
    }
};


int main() {
    std::vector<std::shared_ptr<Foo>> vec{
        std::make_shared<Foo>(), 
        std::make_shared<Foo1>(), // 直接构造Foo1实例,自动向上转型为shared_ptr<Foo>
        std::make_shared<Foo2>()  // 直接构造Foo2实例,自动向上转型为shared_ptr<Foo>
    };

    for (auto &&ptr : vec)
    {
        ptr->Update();
    }
}

修改后运行输出为:

Update idle
Update Foo1
Update Foo2
补充说明

原代码中Foo2的Update是类默认private权限,外部调用会编译报错,因此解法中补充了public权限声明。如果不需要修改父类默认的析构逻辑,直接用virtual ~Foo() = default;声明虚析构即可,不需要额外写实现。

内容的提问来源于stack exchange,提问作者DeerFreak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:06:03