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

C++不用模板能否让单个成员函数指针指向不同类的成员方法?

问题解答

核心结论

原生C++成员函数指针无法直接实现该需求。
不同类的成员函数指针属于完全独立的类型,哪怕函数返回值、参数列表完全一致,void(Foo::*)(FooBar*)和void(Bar::*)(FooBar*)也不存在隐式转换关系,因此无法用同一个原生成员函数指针变量存储两类不同的成员函数指针,你期望的<???>原生语法不存在。

无需自定义模板的实现方案

你可以通过手动类型擦除的方式,用普通函数指针+上下文指针实现统一存储,全程不需要写模板代码,示例如下:

class Foo;
class Bar;
class FooBar 
{
public:
    using FpType = void(*)(void*, FooBar*);
    FooBar(Foo &f, void (Foo::* signal)(FooBar*)) 
        : m_ctx(&f)
        // 无捕获lambda可直接转换为普通函数指针
        , fp([](void* ctx, FooBar* fb) {
            (static_cast<Foo*>(ctx)->*static_cast<void(Foo::*)(FooBar*)>(signal))(fb);
        }) {};
    FooBar(Bar &b, void (Bar::* signal)(FooBar*)) 
        : m_ctx(&b)
        , fp([](void* ctx, FooBar* fb) {
            (static_cast<Bar*>(ctx)->*static_cast<void(Bar::*)(FooBar*)>(signal))(fb);
        }) {};

    // 统一调用入口
    void invoke() {
        fp(m_ctx, this);
    }

protected:
    FpType fp; // 单一通用函数指针

private: 
    void* m_ctx{nullptr}; // 存储Foo/Bar实例上下文
};

该方案原理是用无捕获lambda做适配层,把不同类型的成员函数调用统一转换为相同签名的普通函数调用,不需要额外的类型判断逻辑。

可选简化方案

如果允许使用标准库组件,可以用std::function<void(FooBar*)>实现,代码更简洁易维护:

#include <functional>
class Foo;
class Bar;
class FooBar 
{
public:
    FooBar(Foo &f, void (Foo::* signal)(FooBar*)) 
        : fp(std::bind(signal, &f, std::placeholders::_1)) {};
    FooBar(Bar &b, void (Bar::* signal)(FooBar*)) 
        : fp(std::bind(signal, &b, std::placeholders::_1)) {};

    void invoke() {
        fp(this);
    }

protected:
    std::function<void(FooBar*)> fp;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 00:24:03