如何实现通用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
相关产品推荐
相关产品推荐

