指向不同类的成员函数的指针
Pointer to member functions of different classes
在类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(); }
};
缺点是必须从同一个基类派生所有侦听器。此外,如果同一个类需要有多个侦听器回调,则必须跳过一些障碍。
- 从成员指针到整个结构/类的强制转换
- OOP 中的单成员指针
- 使用结构成员指针在C++中填充结构
- 聚合初始化,将成员指针设置为同一结构成员
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 共享 C++ 的数据成员指针
- 如何声明指向成员内容的成员指针m_pmd/m_pmf并访问它们?
- 从类C++外部调用指向成员方法的成员指针
- 结构成员指针是否自动初始化为零?
- 如何删除类内类类型的类成员指针
- 是否打印指向已定义 int 的成员指针
- 指向常量的成员指针
- 通过此指针访问时的成员差异和自身的成员指针(简单的 QT 示例问题)
- 类数据成员指针的非类型模板参数包无法使用 gcc 编译
- 为什么我不能在同一行中定义两个相同类型的类的成员指针
- 将类成员指针传递给 Lambda 捕获列表 c++11
- 在单一实例类中将成员指针设置为 null 的正确方法是什么
- 无法删除在destructor中的成员指针的课程
- 删除对象而不调用成员指针的析构函数
- 当派生类的基类具有成员指针时,对其进行深层复制