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

如何实现通用add函数将Element派生类对象存入shared_ptr向量

通用add函数实现方案

嘿,这个问题其实用C++模板就能轻松搞定,完全不用给每个派生类都写重载的add函数~

核心思路

问题的根源在于直接传入const Element&会触发对象切片,而且无法自动推导原始派生类类型来构造对应的shared_ptr<Derived>。用模板函数让编译器自动推导传入的派生类类型,就能完美解决这个问题。

基础实现版本

首先我们可以写一个模板版本的add函数,自动适配所有Element的派生类:

#include <vector>
#include <memory>
#include <type_traits> // 用于静态断言

class Element { };
class Button : public Element { };
class Label : public Element { };
class Input : public Element { };

// 存储shared_ptr的vector
std::vector<std::shared_ptr<Element>> element_vec;

// 通用add函数,接收任意Element派生类的左值引用
template <typename Derived>
void add(const Derived& e) {
    // 编译期检查:确保Derived是Element的派生类,避免传入无关类型
    static_assert(std::is_base_of_v<Element, Derived>, "The type must inherit from Element");
    
    // 创建对应派生类的shared_ptr,隐式转换为shared_ptr<Element>后加入vector
    element_vec.push_back(std::make_shared<Derived>(e));
}

优化:支持右值(临时对象)

如果需要支持传入临时对象(比如add(Button{})),可以用万能引用实现一个更通用的版本,同时完美转发参数避免不必要的拷贝:

template <typename Derived>
void add(Derived&& e) {
    static_assert(std::is_base_of_v<Element, Derived>, "The type must inherit from Element");
    
    // 完美转发参数,适配左值和右值
    element_vec.push_back(std::make_shared<Derived>(std::forward<Derived>(e)));
}

使用示例

不管是左值对象还是临时对象,都能直接调用add函数,不需要任何重载:

int main() {
    Button my_btn;
    Label my_label;
    Input my_input;

    // 传入左值对象
    add(my_btn);
    add(my_label);
    add(my_input);

    // 传入临时对象
    add(Button{});
    add(Label{});

    return 0;
}

额外说明

  • static_assert是可选但推荐的:它能在编译期就拦截传入非Element派生类的错误,比运行时错误更友好。
  • 这个方案完全符合你的需求:只需要一个通用函数,就能处理所有Element的派生类,不需要为每个子类单独写重载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:56:06