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

向std::vector存入子类实例,为何调用父类虚方法而非子类?

问题原因与解决方案

问题根源:对象切片

你遇到的是C++里典型的对象切片问题。

当执行v.push_back(Child())时,vector<Parent>只能存放Parent类型的对象。此时编译器会把Child对象中属于Parent的部分拷贝到vector元素中,而Child类独有的数据、虚函数表中指向Child::Test的指针等信息都会被“切掉”。最终vector里存储的只是一个纯粹的Parent对象,调用Test()自然会执行父类的版本。

解决方案:存储指针/智能指针

要保留多态行为,不能直接存储对象实例,得存储指向基类的指针或智能指针。这样vector里的指针会指向完整的子类对象,虚函数机制就能正常工作,调用对应子类的方法。

修改后的示例代码(用智能指针)

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

class ParentAbstract
{
public:
    virtual void Test() = 0;
    virtual ~ParentAbstract() = default; // 必须添加虚析构,防止内存泄漏
};

class Parent : public ParentAbstract
{
public:
    void Test() override
    {
        std::cout << "parent" << std::endl;
    }
};

class Child : public Parent
{
public:
    void Test() override
    {
        std::cout << "child" << std::endl;
    }
};

int main()
{
    std::vector<std::unique_ptr<ParentAbstract>> v;
    v.push_back(std::make_unique<Child>());
    v.at(0)->Test(); // 输出:child
}

关键点说明

  • 使用std::unique_ptr(或std::shared_ptr)管理对象生命周期,避免手动释放指针的麻烦和内存泄漏。
  • 基类ParentAbstract必须添加虚析构函数,这样智能指针销毁对象时,会正确调用子类的析构函数,完成完整的资源清理。
  • 用override关键字显式标记重写的虚函数,能让编译器帮你检查是否正确重写了父类的虚方法,避免拼写错误等问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 13:18:08