问题如下:考虑这段代码:
#include <iostream>
class aClass
{
public:
void aTest(int a, int b)
{
printf("%d + %d = %d", a, b, a + b);
}
};
void function1(void (*function)(int, int))
{
function(1, 1);
}
void test(int a,int b)
{
printf("%d - %d = %d", a , b , a - b);
}
int main()
{
aClass a;
function1(&test);
function1(&aClass::aTest); // <-- How should I point to a's aClass::test function?
}
如何使用a
的aClass::test
作为function1
的参数?我想访问类的成员。
9条答案
按热度按时间rbpvctlc1#
使用函数指针并没有什么错,但是指向非静态成员函数的指针与普通的函数指针不同:成员函数需要在一个对象上调用,该对象作为隐式参数传递给函数。上面的成员函数的签名是,因此
而不是您尝试使用的类型
一种方法是将成员函数设为
static
,在这种情况下,它不需要调用任何对象,并且可以使用void (*)(int, int)
类型。如果你需要访问类 * 和 * 的任何非静态成员,你需要坚持使用函数指针,例如,因为函数是C接口的一部分,你最好的选择是总是传递一个
void*
到你的函数,接受函数指针,并通过一个转发函数调用你的成员,该转发函数从void*
获得一个对象,然后调用成员函数。在一个合适的C++接口中,你可能需要让你的函数接受模板化参数来使用函数对象的任意类类型。如果不需要使用模板化接口,你应该使用类似
std::function<void(int, int)>
的东西:可以为这些创建适当的可调用函数对象,例如使用std::bind()
。使用类类型的模板参数或合适的
std::function<...>
的类型安全方法优于使用void*
接口,因为它们消除了由于强制转换为错误类型而导致错误的可能性。为了阐明如何使用函数指针来调用成员函数,下面是一个示例:
hfsqlsce2#
@Pete Becker的答案是正确的,但是在C++ 11中,您也可以不将
class
示例作为显式参数传递给function1
:cvxl0en23#
指向成员函数的指针与指向函数的指针不同,为了通过指针使用成员函数,你需要一个指向它的指针(很明显)和一个应用它的对象,所以
function1
的合适版本应该是并称之为:
6qftjkof4#
从2011年开始,如果可以更改
function1
,请按如下方式进行更改:(live demo)
还要注意,我修复了损坏的对象定义(
aClass a();
声明了一个函数)。rta7y2nd5#
我问了一个类似的问题(C++ openframeworks passing void from other classes),但我找到的答案更清楚,所以在这里解释未来的记录:
使用std::函数更容易,如下所示:
然后调用为:
或者更容易:
在这里你创建一个lambda来调用通过引用捕获它的对象
zz2j4svz6#
需要注意的是,除非你可以改变接受函数的代码的签名,否则没有(简单的)方法可以做到这一点,那就是尝试在一种没有与函数相同的闭包的语言中实现闭包(C++中闭包的签名是不同的)。
有两种 * 实际 * 的方法可以实现这一点:
1.使用某种类型的单例变量/全局变量来存储闭包,然后传递一个helper函数,该函数使用闭包调用所需的函数。
当然,这有一个明显的缺点,即闭包需要在每次调用之前设置,还有一些线程安全问题。虽然不理想,但在特定环境下可能是可行的
1.使用asmjit或动态编译来动态编译并将函数传递给C代码。这只适用于允许堆部分标记为可执行的机器。它也是非常不可移植的,因为你将编写汇编代码来完成这一点。然而,如果你让它工作,你将确实有一个真正的闭包。尽管与大多数编程语言实现闭包的方式相比,创建闭包的成本要高得多(它们不复制函数汇编,而是使用上下文对象)
1.修补包含函数处理程序的lib/dll,改变它的签名以允许上下文对象。同样,这是一个非常脆弱和非最佳的解决方案。
我最初的回答,并没有真正回答这个问题,但人们发现它很有用:
不知道为什么这个难以置信的简单解决方案已经被放弃了:
输出:
wkyowqbh7#
我把成员函数设为静态的,所有的都可以:
polkgigr8#
如果你实际上不需要使用示例
a
(也就是说,你可以像@mathengineer的answer一样使它成为静态的),你可以简单地传入一个非捕获的lambda。(它衰减为函数指针)Wandbox
注意:如果
aClass
的构建成本很高或者有副作用,这可能不是一个好方法。gajydyqb9#
现在你可以不用再敲你的头了。下面是成员函数的 Package 器,它支持existing函数将普通的C函数作为参数。
thread_local
指令是这里的关键。http://cpp.sh/9jhk3
请就这一办法的任何问题发表评论。
其他应答无法调用现有plain
C
函数:http://cpp.sh/8exun