指向不同类的成员函数的指针

Pointer to member functions of different classes

本文关键字:成员 指针 函数 同类      更新时间:2023-10-16

在类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;
}

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

对"A::setOnConfirmListener()"的调用没有匹配的函数

我理解"指向函数的指针"与"指向成员函数的指针)不同。因此,我还尝试将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,并使用指向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(); }
};

缺点是必须从同一个基类派生所有侦听器。此外,如果同一个类需要有多个侦听器回调,则必须跳过一些障碍。