c++ - 指向不同类成员函数的指针

标签 c++ callback function-pointers

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

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

no matching function for call to 'A::setOnConfirmListener()'

我理解“指向函数的指针”不同于“指向成员函数的指针”。所以我也尝试将 void (*onConfirmCallback) () 更改为 void (B::*onConfirmCallback) () ,但我认为这不好,因为这个指针应该保留对不同类(不是派生自同一基类)的回调,而不仅仅是 B

有没有办法实现这个?

基本上我正在尝试做一些类似 Java 接口(interface)的事情......

最佳答案

使用 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(); }
};

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

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

相关文章:

c++ - main() 如何处理不带省略号的可变数量的参数?

c++ - 复制构造函数没有合适的默认构造函数

c++ - 什么时候使用 const string& 与 const string 比较好

c++ - 传递函数

c++ - 找不到Dlib “' dlib/image_processing/frontal_face_detector.h'文件” Xcode C++控制台应用程序

javascript - 使用回调处理程序在函数内调用父对象方法

JavaScript 闭包回调本身

java - 之间的回调方法

c++ - 使用 C 的 '...' 参数包作为 C++ 模板值?

c++ - 函数指针是否在进程间保持有效?