T::* 在函数参数列表的声明中表示什么?
What does T::* signify in the declaration of a function parameter list?
我在我的代码中声明了一个特定的键盘回调函数:
void keyboardEventCallback(const pcl::visualization::KeyboardEvent &event, void* viewer_void, void* widget_void);
键盘事件是传递给回调函数的实际事件,viewer_void参数是指向生成window用于渲染的PCLVisualizerclass的指针,widget_void 是指向与 Qt 交互的小部件的指针。
在 pcl 的文档中,注册函数传递用于注册键盘函数的参数,如
boost::signals2::connection registerKeyboardCallback(void(T::*callback)(const pcl::visualization::KeyboardEvent&, void*), T& instance, void* cookie=nullptr)
所以我的问题是,注册函数声明中的T::*
是什么意思,为什么我不允许通过这个:
m_vis->registerKeyboardCallback(keyboardEventCallback, (void*)&m_vis, (void*)this);
其中 m_vis
是可视化工具,keyboardcallback
是回调,这是小部件。
为什么我这样注册不了。这是点云库。
这是成员函数的语法。
示例:
class A{
int giveMe5();
};
&A::giveMe5; // will be of type int(A::*)()
为什么类型不同于自由函数和静态成员函数?
因为成员函数有一个隐式参数指向函数被调用的对象。
https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types
说:
The type of this function is different depending on whether it is an ordinary function or a non-static member function of some class:
- Its type is int (*)(char,float)
if an ordinary function
- Its type is int (Fred::*)(char,float)
if a non-static member function of class Fred
what is the meaning of T::* inside the registration function declaration
这是成员指针的语法。我们看一下参数的整个类型和名称:
void(T::*callback)(const pcl::visualization::KeyboardEvent&, void*)
这是一个名为 callback
的变量的声明。它是一个 指向成员函数 的指针。更准确地说,它是指向 class T
.
的成员函数的指针
如果我们把名称从类型中去掉,我们会看得更清楚:
// class name ---v v------- parameters
void(T::*)(const pcl::visualization::KeyboardEvent&, void*)
// ^---- return type
它实际上是指向 class T
的函数成员的指针,即 returns void
。这是一个 strictly 两个参数的函数:const pcl::visualization::KeyboardEvent&
和 void*
.
why am I not allowed to pass this
很简单。看你函数的类型:
using func_type = decltype(keyboardEventCallback);
// hint: the type is: void(*)(const pcl::visualization::KeyboardEvent&, void*, void*)
让我们并排比较这两种类型:
void(*)(const pcl::visualization::KeyboardEvent&, void*, void*)
void(T::*)(const pcl::visualization::KeyboardEvent&, void*)
首先,你的函数不是成员函数,它是一个普通的函数指针。这不是同一类型。然后,你得到了三个参数,因为参数的类型只要求两个。这是不同的。
现在,你怎么解决这个问题?
你可以使用 lambda:
auto myCallback = [](const pcl::visualization::KeyboardEvent& e, void* c) { /* ... */ }
using lambdaType = decltype(myCallback);
// Be careful here, we don't want our lambda to go out of scope when it is called.
m_vis->registerKeyboardCallback(&lambdaType::operator(), myCallback, this);
或者更简单:只需在 class 中定义 keyboardEventCallback
,然后发送:
// don't forget: keyboardEventCallback must receive the same parameter as asked.
m_vis->registerKeyboardCallback(&MyClass::keyboardEventCallback, *this, this);
我在我的代码中声明了一个特定的键盘回调函数:
void keyboardEventCallback(const pcl::visualization::KeyboardEvent &event, void* viewer_void, void* widget_void);
键盘事件是传递给回调函数的实际事件,viewer_void参数是指向生成window用于渲染的PCLVisualizerclass的指针,widget_void 是指向与 Qt 交互的小部件的指针。
在 pcl 的文档中,注册函数传递用于注册键盘函数的参数,如
boost::signals2::connection registerKeyboardCallback(void(T::*callback)(const pcl::visualization::KeyboardEvent&, void*), T& instance, void* cookie=nullptr)
所以我的问题是,注册函数声明中的T::*
是什么意思,为什么我不允许通过这个:
m_vis->registerKeyboardCallback(keyboardEventCallback, (void*)&m_vis, (void*)this);
其中 m_vis
是可视化工具,keyboardcallback
是回调,这是小部件。
为什么我这样注册不了。这是点云库。
这是成员函数的语法。
示例:
class A{
int giveMe5();
};
&A::giveMe5; // will be of type int(A::*)()
为什么类型不同于自由函数和静态成员函数? 因为成员函数有一个隐式参数指向函数被调用的对象。
https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types 说:
The type of this function is different depending on whether it is an ordinary function or a non-static member function of some class:
- Its type isint (*)(char,float)
if an ordinary function
- Its type isint (Fred::*)(char,float)
if a non-static member function of class Fred
what is the meaning of T::* inside the registration function declaration
这是成员指针的语法。我们看一下参数的整个类型和名称:
void(T::*callback)(const pcl::visualization::KeyboardEvent&, void*)
这是一个名为 callback
的变量的声明。它是一个 指向成员函数 的指针。更准确地说,它是指向 class T
.
如果我们把名称从类型中去掉,我们会看得更清楚:
// class name ---v v------- parameters
void(T::*)(const pcl::visualization::KeyboardEvent&, void*)
// ^---- return type
它实际上是指向 class T
的函数成员的指针,即 returns void
。这是一个 strictly 两个参数的函数:const pcl::visualization::KeyboardEvent&
和 void*
.
why am I not allowed to pass this
很简单。看你函数的类型:
using func_type = decltype(keyboardEventCallback);
// hint: the type is: void(*)(const pcl::visualization::KeyboardEvent&, void*, void*)
让我们并排比较这两种类型:
void(*)(const pcl::visualization::KeyboardEvent&, void*, void*)
void(T::*)(const pcl::visualization::KeyboardEvent&, void*)
首先,你的函数不是成员函数,它是一个普通的函数指针。这不是同一类型。然后,你得到了三个参数,因为参数的类型只要求两个。这是不同的。
现在,你怎么解决这个问题?
你可以使用 lambda:
auto myCallback = [](const pcl::visualization::KeyboardEvent& e, void* c) { /* ... */ }
using lambdaType = decltype(myCallback);
// Be careful here, we don't want our lambda to go out of scope when it is called.
m_vis->registerKeyboardCallback(&lambdaType::operator(), myCallback, this);
或者更简单:只需在 class 中定义 keyboardEventCallback
,然后发送:
// don't forget: keyboardEventCallback must receive the same parameter as asked.
m_vis->registerKeyboardCallback(&MyClass::keyboardEventCallback, *this, this);