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

C++如何将抽象基类Drawable的子类存入容器实现多态调用?

解决方案

核心原理

C++容器直接存储对象时,会在容器的连续内存空间中直接构造对应类型的实例。你声明std::vector<Drawable>时,容器所有元素的内存分配、拷贝逻辑都会按照基类Drawable的大小和类型处理,除了抽象类无法实例化的报错外,就算基类可实例化也会出现对象切片问题,丢失子类特有成员,导致多态完全失效。
要实现多态容器,必须存储基类的指针/智能指针,由指针指向堆上分配的子类实例,保留多态特性。

修改步骤

  • 将容器类型改为存储智能指针,优先使用std::unique_ptr(独占所有权场景),需要多所有者共享的场景可以用std::shared_ptr
  • 修复子类Square重复定义name成员的bug:子类不需要重复定义基类已有的成员,否则你在构造函数中赋值的是子类独有的name,基类name始终为空,会导致之前写的operator==判断完全失效
  • 插入元素时直接构造子类实例的智能指针存入容器
  • 遍历容器时调用draw()即可自动触发多态

修复后可运行代码

#include <vector>
#include <string>
#include <memory> // 引入智能指针头文件

struct Drawable
{
public:
    std::string name;
    virtual void draw() = 0;
    Drawable() = default;
    virtual ~Drawable() = default;
    Drawable(const Drawable &other) = default; // 拷贝构造补充const符合通用规范
    Drawable(Drawable &&other) = default;
    Drawable &operator=(const Drawable &other) = default;
    Drawable &operator=(Drawable &&other) = default;
};

bool operator==(const Drawable &lhs, const Drawable &rhs)
{
    return lhs.name == rhs.name;
}

bool operator!=(const Drawable &lhs, const Drawable &rhs)
{
    return !(lhs == rhs);
}

struct Square : public Drawable
{
    Square(std::string name)
    {
        this->name = std::move(name);
    }
    void draw() override // 加override关键字显式标记重写,编译期就能检查出函数签名写错的问题
    {
        /* 业务逻辑 */
    }
};

int main()
{
    std::vector<std::unique_ptr<Drawable>> drawables;

    // 构造子类实例的智能指针存入容器
    drawables.push_back(std::make_unique<Square>("reddy"));
    // 可继续添加其他Drawable子类的实例
    // drawables.push_back(std::make_unique<Circle>("blue_circle"));

    // 遍历统一调用draw,自动触发多态
    for (auto &item : drawables)
    {
        item->draw();
    }
}

搜索方向补充

你之前没找到相关教程是关键词选择的问题,搜索C++ 多态容器、C++ 抽象类 存储到容器、C++ 对象切片就可以找到对应的讲解内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 08:45:02