调用从另一个 class 传递的回调

Calling a callback passed from another class

我想在另一个 (X) 中注册一个 class (Y) 的回调处理程序(方法)。由于可能的堆分配,我无法使用 std::function,并且我必须有权访问注册处理程序的 class 的成员。我也想避免静态函数。 我想出了一些办法,但一直坚持调用回调:

template<class T>
using clbkType = void(T::*)(void);

template<class T>
class X
{
public:

    void registerClbck(clbkType<T> clbk) {
        callback = clbk;
    }

    void call() {
        callback(); // ERROR C2064: term does not evaluate to a function taking 0 arguments.
        //(((X<T>*)this)->X<T>::callback)(); // same error

    }
private:
    clbkType<T> callback;
};

class Y
{
public:

    Y() {
        x.registerClbck(&Y::handler);
    }

    // just for a test: fire a callback in class X
    void fire() {
        x.call();
    }

    int getA() { return a; }
private:
    int a{ 0 };
    X<Y> x{};

    void handler() {
        a = 5;
    }
};

int main()
{
    Y y;
    y.fire();
    return y.getA();
}

link 编码:https://godbolt.org/z/PhY41xsWE

PS。我不确定这是否是一个安全的解决方案,所以请对此发表任何评论。

谢谢!

成员函数指针需要一个特定的class对象来调用,所以你需要这样做:

template<class T>
class X
{
public:
    // ...
    void call(T& obj) {
      (obj.*callback)();
    }
    // ...
};

class Y
{
public:
    // just for a test: fire a callback in class X
    void fire() {
      x.call(*this);
    }
    // ...  
};

Demo.

成员函数指针需要实例调用

如果你想绑定实例,这里有一个可能的实现方式。

template<typename T>
struct member_callback {
    T* instance;
    void(T::*callback)();
    void operator()(){(instance->*callback)();}
};

template<typename T>
struct X{
    void registerClbck(member_callback<T> clbk) { callback = clbk; }
    void call() { callback(); }
    member_callback<T> callback;
};

struct Y{
public:
    Y() { x.registerClbck({this,&Y::handler}); }
    void fire() { x.call(); }
    int getA() { return a; }
private:
    int a{ 0 };
    X<Y> x{};
    void handler(){ a = 5; }
};

int main()
{
    Y y;
    y.fire();
    return y.getA();
}