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

如何在C++中为支持不同参数的成员函数指针编写typedef?

问题描述

现有一套基于用户输入执行类成员函数的实现,核心定义如下:

typedef int(A::*FUNCPTR)(); 
std::map<const std::string, FUNCPTR> func_map;

初始化代码:

func_map["sum"]  = &A::cmd_sum;
func_map["print"]  = &A::cmd_print;

类A中的函数声明:

int cmd_sum();
int cmd_print();

程序会根据用户输入调用对应函数,两个函数均返回int类型。

现在需要扩展功能:让cmd_sum接收两个int参数,cmd_print保持无参(用于打印Hello world),要兼容以下函数声明:

int cmd_sum(int a, int b);
int cmd_print();
解决方案

不同参数的成员函数指针类型不兼容,没法直接存入同一个std::map,必须用统一的可调用包装类型来适配,这里推荐两种实现方式:

方式一:用std::function统一包装(兼容所有C++版本)

这是最通用的方案,通过lambda把不同参数的成员函数转换成统一的包装类型。

1. 修改类型定义和map

引入<functional>和<vector>头文件,替换原有的指针定义:

#include <functional>
#include <vector>

// 统一包装类型:接收A的实例引用、参数列表,返回int
using FuncWrapper = std::function<int(A&, const std::vector<int>&)>;
std::map<const std::string, FuncWrapper> func_map;

2. 重新初始化map

用lambda把两个函数适配成FuncWrapper类型,同时处理参数校验:

// 适配带两个参数的cmd_sum
func_map["sum"] = [](A& obj, const std::vector<int>& args) -> int {
    if (args.size() != 2) {
        // 参数数量不对时返回错误码,可根据需求调整
        return -1;
    }
    return obj.cmd_sum(args[0], args[1]);
};

// 适配无参的cmd_print,直接忽略参数列表
func_map["print"] = [](A& obj, const std::vector<int>&) -> int {
    return obj.cmd_print();
};

3. 修改调用逻辑

解析用户输入的命令和参数(把输入的数字转成std::vector<int>),然后调用包装后的函数:

// 示例调用逻辑
A obj;
std::string input_cmd = "sum";
std::vector<int> input_args = {3, 5};

auto cmd_iter = func_map.find(input_cmd);
if (cmd_iter != func_map.end()) {
    int result = cmd_iter->second(obj, input_args);
    // 这里可以处理返回结果,比如打印或判断执行状态
} else {
    // 处理未知命令的情况
}

方式二:用std::variant存储不同指针(C++17及以上)

如果项目用的是C++17或更高版本,可以用std::variant直接存储不同类型的成员函数指针,调用时通过类型判断执行:

1. 修改类型定义和map

引入<variant>头文件,定义两种成员函数指针类型,用variant作为map的值:

#include <variant>

// 定义两种成员函数指针类型
using FuncNoParam = int(A::*)();
using FuncTwoParams = int(A::*)(int, int);

std::map<const std::string, std::variant<FuncNoParam, FuncTwoParams>> func_map;

2. 初始化map

直接存入不同类型的成员函数指针:

func_map["sum"] = &A::cmd_sum;
func_map["print"] = &A::cmd_print;

3. 修改调用逻辑

用std::visit遍历variant,通过constexpr判断类型后调用:

// 示例调用逻辑
A obj;
std::string input_cmd = "print";
std::vector<int> input_args = {};

auto cmd_iter = func_map.find(input_cmd);
if (cmd_iter != func_map.end()) {
    std::visit([&](auto&& func) {
        using FuncType = std::decay_t<decltype(func)>;
        if constexpr (std::is_same_v<FuncType, FuncNoParam>) {
            obj.*func();
        } else if constexpr (std::is_same_v<FuncType, FuncTwoParams>) {
            if (input_args.size() == 2) {
                obj.*func(input_args[0], input_args[1]);
            }
        }
    }, cmd_iter->second);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:52:44