gpt4 book ai didi

不同类之间非静态函数的C++回调

转载 作者:行者123 更新时间:2023-11-27 23:22:57 30 4
gpt4 key购买 nike

我有一个 A 类,我打算在它与设备驱动程序交互时将其放入共享库中。

我有一个 B 类,将来可能是 C、D、E...,它将使用共享库中的 A 类。

我想要在类 A 中设置回调函数的功能,以便当特定事件发生时,类 B、C、D、E ... 的非静态成员函数应由类 A 调用。

我在谷歌上搜索了 C++ 中的回调函数,但发现 C 风格的回调定义不支持非静态成员函数。

可以使用函数指针来完成吗?

请在不违反 OOPS 概念的情况下对 C++ 中的回调提出一些建议。

我还想到了一个名为“Boost”的库,它提供了类似的功能,但我想尽可能避免额外库的开销。是否建议将 Boost 用于回调函数?

编辑: B、C、D、E 将不共享任何层次结构,它们将是完全独立的类。但是它们都会有 A 类的对象。A 类也会有一个公共(public)函数来设置回调函数。

最佳答案

如果您真的想避免多态函数包装器的几乎不重要的开销,一个选择是使这些函数静态并让它们采用“用户数据”void* 参数,指向该函数所属的类的适当实例。在静态函数内部,然后转换回适当的类型:

#include <iostream>

struct A{
typedef void (*callback_type)(void*, int);
callback_type callback;
void* user_data;
void set_callback(callback_type cb, void* ud){
callback = cb; user_data = ud;
}
void invoke(){ callback(user_data, 42); }
};

struct B{
static void cb_foo(void* vself, int data){
B* self = static_cast<B*>(vself);
self->foo(data);
}
void foo(int data){ std::cout << data * 2 << "\n"; }
};

struct C{
static void cb_bar(void* vself, int data){
C* self = static_cast<C*>(vself);
self->bar(data);
}
void bar(int data){ std::cout << data / 2 << "\n"; }
};

int main(){
A a;
B b;
a.set_callback(&B::cb_foo, &b);
a.invoke();
C c;
a.set_callback(&C::cb_bar, &c);
a.invoke();
}

Live example on Ideone.

不过,我个人会推荐使用 std::function,因为上面的内容在可接受的回调方面受到严格限制。 std::function 是一个多态函数包装器,这意味着它可以采用普通函数指针、成员函数指针甚至仿函数(函数对象)并以相同的方式调用它们。与允许您将参数绑定(bind)到函数的 std::bind 一起,您可以轻松回调成员函数。 Boost 也提供它们(Boost.FunctionBoost.Bind)。

#include <iostream>
#include <functional> // C++11
//#include <boost/function.hpp>
//#include <boost/bind.hpp>

struct A{
std::function<void(int)> callback;
void invoke(){ callback(42); }
};

struct B{
void foo(int data){ std::cout << data * 2 << "\n"; }
};

struct C{
void bar(int data){ std::cout << data / 2 << "\n"; }
};

int main(){
using namespace std::placeholders; // namespace for argument placeholders for std::bind
// not needed for Boost.Bind
A a;
B b;
a.callback = std::bind(&B::foo, &b, _1);
a.invoke();
C c;
a.callback = std::bind(&C::bar, &c, _1);
a.invoke();
};

Live example on Ideone.

基本上 std::bind 会自动执行您在第一个版本中必须手动执行的操作,它会保存对象指针并调用其成员函数。但是,它不是通过 void* 指针来执行此操作,而是 std::bind 为每个不同的对象指针返回不同的绑定(bind)器类型。这就是您需要 std::function 的原因,因为它不关心您传递给它的内容。

关于不同类之间非静态函数的C++回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11522422/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com