为什么我不能引用指向实例化对象的函数的指针?
Why can't I reference a pointer to a function of an instantiated object?
EDIT:std::function
+ lambda 来救援。请参阅检查答案。
编辑:我添加了更多细节,我想要一个通用的解决方案,而不是绑定到类B
的定义。
在下面的示例中,我尝试将一个类中的函数指针设置为另一个类实例中的函数(具有相同的函数指针类型(,Microsoft C++告诉我:
C++ a pointer to a bound function may only be used to call the function
是因为包含回调的对象可能在第一个对象之前被破坏吗?我正在将一些 Python 转换为 C++ 这种模式在 Python 中似乎不是问题。
我发现解决方法是使函数static
(和成员数据(,但我只是在黑客攻击,直到编译器关闭并且代码正常工作,而不是我最喜欢的编程模式。
如果不允许这种模式,关于如何在没有静态对象/函数的情况下动态执行此操作的任何建议?
#include <iostream>
#include <string>
typedef void (*callback_function_a)(int);
struct A
{
A() {
cbk = nullptr;
};
void print_int(void)
{
if (cbk != nullptr) {
cbk(10);
}
}
void set_callback(callback_function_a _cbk)
{
cbk = _cbk;
};
callback_function_a cbk;
};
struct B
{
B(std::string _header)
{
header = _header;
}
void print(int x) {
std::cout << header << x << std::endl;
}
std::string header;
};
void print(int x)
{
std::cout << "Non-member func: " << x << std::endl;
}
int main()
{
A classA;
B classB(std::string("MessageFrom classB:"));
/// How do I make both of these work? I want to be able to pass in any
/// function of type callback_function_a?
classA.set_callback(print); // OK
classA.set_callback(classB.print); // <--- error here
}
指向自由函数的函数指针和指向成员函数的函数指针是两回事。要解决这个问题,我们需要某种包装器。
这是std::function
的一个很好的用例。它是具有给定签名的类型擦除可调用对象。
为了使它更通用,您应该set_callback
模板,以便您可以接受可分配给std::function
的任何类型的可调用对象。
#include <iostream>
#include <string>
#include <functional>
struct A {
A() {
cbk = nullptr;
};
void print_int(void) {
if (cbk != nullptr) {
cbk(10);
}
}
template <typename Func>
void set_callback(Func _cbk) {
cbk = _cbk;
};
std::function<void(int)> cbk;
};
struct B {
B(std::string _header) {
header = _header;
}
void print(int x) {
std::cout << header << x << std::endl;
}
std::string header;
};
void print(int x) {
std::cout << "Non-member func: " << x << std::endl;
}
int
main() {
A classA;
B classB(std::string("MessageFrom classB:"));
/// How do I make both of these work? I want to be able to pass in any
/// function of type callback_function_a?
classA.set_callback(print); // OK
classA.set_callback([&](int i) { classB.print(i); }); // <--- now works as well
}
如果您不熟悉像[&](int i) { classB.print(i); }
这样的lambda,请看一下这里。
你的代码有几个问题。
首先,成员函数指针和自由函数指针类型不同。对于成员函数指针,您应该有
typedef void (B::*callback_function_a)(int);
// ^^^^
// or
// using callback_function_a = void (B::*)(int);
其次,传递成员函数应该有语法&ClassName::MemberFunction
,意思是,你必须
classA.set_callback(&B::print);
最后但并非最不重要的一点是,您需要有一个类的实例来调用其成员函数。因此在这里,
void print_int(void) {
if (cbk != nullptr) {
// cbk(10); // will not work
}
}
仅调用成员函数指针是行不通的。您应该有一个B
类的实例来调用其成员。你需要,像
#include <functional> // std::invoke (required C++17)
void print_int()
{
if (cbk != nullptr)
{
(/*instance of B class*/.*cbk)(10);
// or simply using `std::invoke`
// std::invoke(cbk, /*instance of B*/, 10);
}
}
除了 Jejo 的出色答案之外,还可以添加一件事,那就是,您可以使成员函数static
,然后将其直接作为参数传递set_callback()
。
例:
class B {
...
static void print(int x) {
// can't use class members in static member functions
std::cout << /* header << */ x << std::endl;
}
...
};
在main()
classA.set_callback(&B::print);
- 如何创建对象函数指针C++映射?
- 为什么我可以改变常量对象中的成员变量,这是返回常量对象函数的结果?
- 如何将对象函数的实例传递给另一个函数
- 调用模板函数的问题"No matching function for call"参数:迭代器、对象函数
- makefile对我的名称空间对象/函数/构造函数的不确定引用
- 将对象函数转换为函数指针
- 非对象函数/类函数C++
- 线程对象函数 C++
- C 将成员对象函数分配给类成员功能
- 使用基本指针调用派生对象函数
- 可以(通过编译器)使用多少个线程来初始化全局对象(函数main之前)
- C++类对象函数
- 对对象::函数的未定义引用
- 无法弄清楚将多个对象函数作为单独的线程调用的语法
- 在提升作用域出口中调用对象函数
- 使用基指针来使用派生对象函数
- 在for_each lambda 中调用对象函数
- C++:: 模板函数 - 从对象函数获取对象的地址
- Qt5 未解析的外部静态元对象函数
- 通过变量使用对象和对象函数