C 函数回调与 C++ 方法回调
Callback from C function vs from C++ method
我有 Foo class 和 bar() 方法。
我还有一个 bar2() 函数(在任何 class 之外)
还有一个 Xpto class,我需要用一些回调来设置构造函数。
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 对象?
因为 myFoo.bar
的签名不等于 std::function<void()>
(因为它是成员函数)。您可以使用 std::bind
(并查看使用成员函数指针的正确语法)。
Xpto x2(std::bind(&Foo::bar, std::ref(myFoo)));
您正在为 Xpto x1(bar2);
使用隐式转换。它调用 std::function<void()>
的隐式构造函数从 bar2
.
创建一个
在第二种情况下,您提供的成员函数没有 void()
的签名。相反,如果是 void Foo:*()
(指向成员函数的指针)。
要工作,您必须像这样使用 std::bind
:
Xpto x2(std::bind(&Foo::bar, myFoo));
因为没有 ()
s 的 myFoo.bar
实际上不是合法的 C++ 表达式(尽管这样的事情在 python 中是完全有意义的),而 bar2
只是一个指向返回 void
的 nullary 自由函数的指针,它可以转换为 std::function<void()>
。
引用成员函数的正确方法是 &Foo::bar
,然后您还需要提供 Foo
的实例。您可以执行以下操作之一:
Xpto x2(std::bind(&Foo::bar, myFoo));
Xpto x2([myFoo]{ myFoo.bar(); });
另请注意,通常您不想在std::function<Sig>
之前接受争论。更喜欢将构造函数编写为:
template <typename F>
Xpto(F func) {
// if you really need a std::function, create it here
}
如果你想使用方法,你应该为它使用一个签名,如:
class Xpto
{
//...
public:
template <class T>
Xpto(void (T::* func)())
{
//do stuff..
}
Xpto(std::function<void()> &callback)
{
//do stuff..
}
//...
}
这一行 void (T::* func)()
表示您将接受一个 return 无效的方法,并且不从对象 T 接收任何参数作为参数。
然后这样使用:
Xpto x2(&myFoo::bar);
我有 Foo class 和 bar() 方法。 我还有一个 bar2() 函数(在任何 class 之外) 还有一个 Xpto class,我需要用一些回调来设置构造函数。
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 对象?
因为 myFoo.bar
的签名不等于 std::function<void()>
(因为它是成员函数)。您可以使用 std::bind
(并查看使用成员函数指针的正确语法)。
Xpto x2(std::bind(&Foo::bar, std::ref(myFoo)));
您正在为 Xpto x1(bar2);
使用隐式转换。它调用 std::function<void()>
的隐式构造函数从 bar2
.
在第二种情况下,您提供的成员函数没有 void()
的签名。相反,如果是 void Foo:*()
(指向成员函数的指针)。
要工作,您必须像这样使用 std::bind
:
Xpto x2(std::bind(&Foo::bar, myFoo));
因为没有 ()
s 的 myFoo.bar
实际上不是合法的 C++ 表达式(尽管这样的事情在 python 中是完全有意义的),而 bar2
只是一个指向返回 void
的 nullary 自由函数的指针,它可以转换为 std::function<void()>
。
引用成员函数的正确方法是 &Foo::bar
,然后您还需要提供 Foo
的实例。您可以执行以下操作之一:
Xpto x2(std::bind(&Foo::bar, myFoo));
Xpto x2([myFoo]{ myFoo.bar(); });
另请注意,通常您不想在std::function<Sig>
之前接受争论。更喜欢将构造函数编写为:
template <typename F>
Xpto(F func) {
// if you really need a std::function, create it here
}
如果你想使用方法,你应该为它使用一个签名,如:
class Xpto
{
//...
public:
template <class T>
Xpto(void (T::* func)())
{
//do stuff..
}
Xpto(std::function<void()> &callback)
{
//do stuff..
}
//...
}
这一行 void (T::* func)()
表示您将接受一个 return 无效的方法,并且不从对象 T 接收任何参数作为参数。
然后这样使用:
Xpto x2(&myFoo::bar);