如何避免微控制器菜单框架代码中频繁出现std::make_shared调用?
解决方案
针对你在微控制器UI菜单框架中遇到的std::make_shared重复书写问题,以下是几种无需宏定义的优雅解决方案:
1. 封装子节点添加方法(最推荐)
在MenuNode基类中添加一个模板方法,将创建shared_ptr和添加子节点的逻辑封装在一起,彻底避免手动调用std::make_shared:
#include <memory> #include <vector> #include <functional> #include <string> class MenuNode { public: virtual void execute() = 0; virtual ~MenuNode() = default; // 封装子节点添加逻辑 template<typename Derived, typename... Args> void add_subnode(Args&&... args) { subnodes.emplace_back(std::make_shared<Derived>(std::forward<Args>(args)...)); } protected: std::vector<std::shared_ptr<MenuNode>> subnodes; }; class ListMenuNode : public MenuNode { public: ListMenuNode(const std::string& name, std::function<void()> cb) : name_(name), callback_(cb) {} void execute() override { callback_(); } private: std::string name_; std::function<void()> callback_; };
使用方式:
int main() { auto main_menu = std::make_shared<ListMenuNode>("Main Menu", []{}); // 无需手动写std::make_shared,直接传递子类构造参数 main_menu->add_subnode<ListMenuNode>("Settings", []{ // 设置菜单逻辑 }); main_menu->add_subnode<ListMenuNode>("About", []{ // 关于菜单逻辑 }); }
这种方案的优势是完全隐藏了指针创建细节,代码可读性最高,同时利用完美转发保证构造参数传递的效率。
2. 子类静态创建方法
给每个子类添加静态工厂方法,将std::make_shared的调用封装在内部:
class ListMenuNode : public MenuNode { public: // 静态工厂方法 static std::shared_ptr<MenuNode> create(const std::string& name, std::function<void()> cb) { return std::make_shared<ListMenuNode>(name, cb); } // 构造函数可以设为私有,强制通过工厂方法创建 ListMenuNode(const std::string& name, std::function<void()> cb) : name_(name), callback_(cb) {} void execute() override { callback_(); } private: std::string name_; std::function<void()> callback_; };
使用方式:
main_menu->subnodes.push_back(ListMenuNode::create("Settings", []{ // 设置菜单逻辑 }));
这种方案的好处是每个子类可以根据自身构造参数定制工厂方法,还能通过私有化构造函数强制规范对象创建方式,避免错误的实例化。
3. 基类通用静态工厂方法
在MenuNode基类中定义一个模板静态方法,支持创建任意子类的shared_ptr:
class MenuNode { public: virtual void execute() = 0; virtual ~MenuNode() = default; // 通用工厂方法 template<typename Derived, typename... Args> static std::shared_ptr<MenuNode> create(Args&&... args) { return std::make_shared<Derived>(std::forward<Args>(args)...); } protected: std::vector<std::shared_ptr<MenuNode>> subnodes; };
使用方式:
main_menu->subnodes.push_back(MenuNode::create<ListMenuNode>("Settings", []{ // 设置菜单逻辑 }));
这种方案无需每个子类单独写工厂方法,适合子类较多且构造逻辑简单的场景,但需要显式指定子类模板参数。
4. 类型别名简化(轻量方案)
如果不想修改类结构,可以用using别名简化std::make_shared的书写:
// 定义别名,缩短书写长度 template<typename T> using make_menu = std::make_shared<T>;
使用方式:
main_menu->subnodes.push_back(make_menu<ListMenuNode>("Settings", []{ // 设置菜单逻辑 }));
这种方案改动最小,只是语法层面的简化,适合快速解决重复书写问题,但本质还是需要手动指定类型。
内容的提问来源于stack exchange,提问作者akasaka
相关产品推荐
相关产品推荐

