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

如何避免微控制器菜单框架代码中频繁出现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 03:44:50