A类中,我有一个成员函数,该成员函数应该从其他类接收指向函数的指针。所有这些功能都具有相同的签名(接收类型和返回类型)。

像这样:

class A{
private:
    void (*onConfirmCallback) (); //pointer to function
public:
    void setOnConfirmListener(void (*callback) ()); //member function that receives another member function from another class, and uses the pointer above to point to it
}

定义:
void A::setOnConfirmListener(void (*callback)())
{
    onConfirmCallback = callback;
}

A类中的某个时刻,我调用了回调函数:
onConfirmCallback();

B类中,我设置了回调:
class B{
private:
    A a;
public:
    B();
    foo();
}

和定义:
B::B(){
    a.setOnConfirmListener(foo);
}
B::foo(){
    cout << "foo called" << endl;
}

我还有另一个类C,它也有一个A的实例,并且还设置了一个回调:
class C{
private:
    A a;
public:
    C();
    foo2();
}

和定义:
C::C(){
    a.setOnConfirmListener(foo2);
}
C::foo2(){
    cout << "foo2 called" << endl;
}

我尝试了不同的声明变体,上面的代码生成此错误:



我知道“函数指针”与“成员函数指针”不同。因此,我也尝试将void (*onConfirmCallback) ()更改为void (B::*onConfirmCallback) (),但我认为这不好,因为此指针应保存指向不同类(不是从相同基类派生的)的回调,而不仅仅是B

有办法实现吗?

基本上我正在尝试做类似Java的界面的事情...

最佳答案

使用std::function而不是函数指针。

class A {
private:
    std::function <void()> onConfirmCallback; //pointer to function
public:
    void setOnConfirmListener(std::function <void()>);
};

您可以将非成员函数直接传递给setOnConfirmListener。对于成员函数,需要一个对象来调用它们:
class B {
private:
    A a;
public:
    B();
    void foo();
};

B::foo(); // invalid and makes no sense
B* b = new B; b->foo(); // OK

因此下面的行也不起作用:
a.setOnConfirmListener(&B::foo); // invalid and makes no sense

您可以使用std::bind将对象及其成员函数一起传递:
a.setOnConfirmListener(std::bind(&B::foo, b)); // OK
b可以是B&B*std::shared_ptr<B>

使用this(或*this)作为bind的第二个参数可能会有些危险,因为您现在有责任监视对象何时停止存在并注销其所有关联的侦听器。一种解决方法是从enable_shared_from_this派生您的对象,并使用std::shared_ptr代替原始的this指针。这意味着您的对象只有在至少一个回调中被注册为侦听器后才被销毁。

一种替代方法是从同一个抽象基类(例如Listener)派生所有侦听器,并使用指向侦听器的指针而不是函数指针。
class Listener
{
  public:
    virtual void callback() = 0;
};

class A {
private:
    std::shared_ptr<Listener> listener; // or another smart pointer
public:
    void setOnConfirmListener(std::shared_ptr<Listener> listener);
};

class B : public Listener {
private:
    A a;
public:
    B();
    void foo();
    void callback() { foo(); }
};

缺点是必须从同一基类派生所有侦听器。同样,如果同一类需要具有多个侦听器回调,则必须跳过一些麻烦。

关于c++ - 指向不同类的成员函数的指针,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34307033/

10-09 06:40
查看更多