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

如何实现指向不同返回类型类Getter的多用途成员函数指针?

实现指向任意返回类型Getter的通用"指针"

嘿,这个需求我懂——想搞一个能指向不同返回类型Getter的通用“指针”是吧?普通的C++成员函数指针因为强类型绑定(比如int (MyClass::*)()和std::string (MyClass::*)()是完全不同的类型),肯定没法直接用同一个变量存储。咱们得靠类型擦除或者变体类型来绕开这个限制,下面给你两种实用的实现思路:

方案1:用std::variant存储已知类型的Getter指针

如果你已经明确知道所有Getter的返回类型(比如int和string),用std::variant是最高效的选择——它不需要动态分配内存,直接把不同类型的成员函数指针存在一个可判别类型的容器里。

完整代码示例

#include <variant>
#include <string>
#include <stdexcept>

class MyClass {
private:
    int i = 42;
    std::string str = "hello";
public:
    int getI() { return i; }
    std::string getStr() { return str; }
};

// 定义变体类型,包含所有可能的Getter成员函数指针
using GetterVariant = std::variant<int (MyClass::*)(), std::string (MyClass::*)()>;

// 辅助调用函数:根据目标返回类型提取并调用对应的Getter
template<typename ResultType>
ResultType call_getter(MyClass& obj, GetterVariant& getter_var) {
    auto getter_ptr = std::get_if<ResultType (MyClass::*)()>(&getter_var);
    if (!getter_ptr) {
        throw std::bad_variant_access();
    }
    return (obj.**getter_ptr)();
}

int main() {
    MyClass obj;
    GetterVariant pointerToAnyMethod;

    // 指向getI()方法
    pointerToAnyMethod = &MyClass::getI;
    int gotI = call_getter<int>(obj, pointerToAnyMethod); // gotI = 42

    // 切换指向getStr()方法
    pointerToAnyMethod = &MyClass::getStr;
    std::string gotStr = call_getter<std::string>(obj, pointerToAnyMethod); // gotStr = "hello"
}

思路解释

  • GetterVariant把所有合法的Getter类型打包成一个变体,编译器会跟踪当前存储的是哪种类型。
  • call_getter模板函数需要你明确指定返回类型,它会尝试从变体中提取对应类型的成员函数指针,成功就调用,失败则抛出异常。

方案2:用类型擦除包装类支持任意返回类型

如果未来可能新增其他返回类型的Getter,不想每次都修改变体定义,可以用类型擦除的包装类,配合std::any来存储返回值,实现完全通用的Getter指针。

完整代码示例

#include <functional>
#include <string>
#include <memory>
#include <any>
#include <stdexcept>

class MyClass {
private:
    int i = 42;
    std::string str = "hello";
public:
    int getI() { return i; }
    std::string getStr() { return str; }
};

class AnyGetter {
private:
    // 抽象基类:定义统一的调用接口
    class GetterConcept {
    public:
        virtual ~GetterConcept() = default;
        virtual std::any call(MyClass& obj) const = 0;
    };

    // 模板实现类:包装具体类型的Getter
    template<typename ResultType>
    class GetterModel : public GetterConcept {
    private:
        ResultType (MyClass::*getter_func)();
    public:
        GetterModel(ResultType (MyClass::*func)()) : getter_func(func) {}
        std::any call(MyClass& obj) const override {
            return (obj.*getter_func)();
        }
    };

    std::unique_ptr<GetterConcept> impl;
public:
    // 构造函数:接受任意类型的Getter成员函数指针
    template<typename ResultType>
    AnyGetter(ResultType (MyClass::*func)()) 
        : impl(std::make_unique<GetterModel<ResultType>>(func)) {}

    // 重载调用运算符:返回std::any类型的结果
    std::any operator()(MyClass& obj) const {
        if (!impl) {
            throw std::runtime_error("Getter not initialized");
        }
        return impl->call(obj);
    }
};

int main() {
    MyClass obj;
    
    // 指向getI()
    AnyGetter pointerToAnyMethod(&MyClass::getI);
    int gotI = std::any_cast<int>(pointerToAnyMethod(obj)); // 42

    // 切换指向getStr()
    pointerToAnyMethod = AnyGetter(&MyClass::getStr);
    std::string gotStr = std::any_cast<std::string>(pointerToAnyMethod(obj)); // "hello"
}

思路解释

  • 用GetterConcept抽象基类隐藏具体Getter的类型,GetterModel模板类负责包装不同类型的成员函数指针。
  • 调用时返回std::any类型,你需要用std::any_cast把它转换成目标类型(转换错误会抛出异常)。

关键注意点

C++是强类型语言,没法做到完全“无类型”的通用指针——你要么提前知道所有可能的返回类型(方案1),要么在调用时明确指定要转换的类型(方案2)。两种方案都能满足你的需求,选哪个取决于你是否需要扩展新的Getter类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:07:51