我有一个带有bar()方法的Foo类。 我也有一个bar2()函数(在任何类之外) 还有一个Xpto类,我需要用一些回调来设置构造函数。
class Foo
{
//...
public:
bar()
{
//do stuff..
}
//...
}
//isolated C function outside class
void bar2()
{
}
class Xpto
{
//...
public:
Xpto(std::function<void()> &callback)
{
//do stuff..
}
//...
}
int main()
{
Xpto x1(bar2); // <---- compiles
Foo myFoo;
Xpto x2(myFoo.bar); // <--- doesn't compile
return 0;
}
为什么我可以使用Foo对象的回调方法创建Xpto对象?
答案 0 :(得分:3)
因为myFoo.bar
的签名不等于std::function<void()>
(因为它的成员函数)。您可以使用std::bind
(并查看使用成员函数指针的正确语法)。
Xpto x2(std::bind(&Foo::bar, std::ref(myFoo)));
答案 1 :(得分:2)
如果你想要使用方法,你应该使用它的签名,如:
class Xpto
{
//...
public:
template <class T>
Xpto(void (T::* func)())
{
//do stuff..
}
Xpto(std::function<void()> &callback)
{
//do stuff..
}
//...
}
这一行void (T::* func)()
表示你将接受一个返回void的方法,并且不接受来自objetc T的参数作为参数。
并使用那样:
Xpto x2(&myFoo::bar);
答案 2 :(得分:1)
您正在使用Xpto x1(bar2);
的隐式转换。它正在调用std::function<void()>
的隐式构造函数来从bar2
创建一个。
在第二种情况下,您提供的成员函数没有void()
的签名。如果是void Foo:*()
(指向成员函数的指针)。
要工作,您必须使用std::bind
,如下所示:
Xpto x2(std::bind(&Foo::bar, myFoo));
答案 3 :(得分:1)
因为没有myFoo.bar
的{{1}}实际上并不是一个合法的C ++表达式(尽管这样的事情在python中是完全有意义的),而()
只是指向返回bar2
的无效函数的指针,该函数可转换为void
。
引用成员函数的正确方法是std::function<void()>
,然后您还需要提供&Foo::bar
的实例。你可以做其中一个:
Foo
另请注意,通常您不想要Xpto x2(std::bind(&Foo::bar, myFoo));
Xpto x2([myFoo]{ myFoo.bar(); });
采用arguemnts。更喜欢将构造函数编写为:
std::function<Sig>