将类Member函数作为参数传递
Passing a class Member function as an Argument
我有一个如下所示的类和一个如下的主方法:
class Mesh
{
public:
void draw()
void draw(){}
}
int main(int argc,char* argv[])
{
Mesh mesh;
glutDisplayFunc(mesh.draw);
}
因此,我想传递一个对象的成员函数作为参数,但编译器显示以下错误消息:
error: argument of type ‘void (Mesh::)()’ does not match ‘void (*)()’
我做错了什么?
由于draw
是一个非静态成员函数,它需要一个类的实例来操作。
在纯C++中,您将使用函数对象(也称为"函子",请参见std::function
或其前身boost::function
(。遗憾的是,这在C或C API中不是一个选项。
在这种情况下,由于没有数据被传递给回调,因此必须创建某种静态函数(类静态或文件静态(,以便在调用它时做正确的事情。
如果你只有一个Mesh
,那么很容易:要么让类中的所有东西都是静态的(在这种情况下,它基本上是一个命名空间(,要么让一个非成员函数对你的Mesh
:的一个实例调用draw
// at some global-ish file scope...
// we define our class
class Mesh { ... };
// and here's the one global instance of it
Mesh myOneMesh;
// and here is our global / static function that "knows"
// which instance to draw
void drawMyOneMesh() { myOneMesh.draw(); }
// then, in the main flow of your program:
glutDisplayFunc( &drawMyOneMesh );
如果有多个网格,则最好将其从当前窗口中设置关键帧。在不太了解你的应用程序或GLUT API的情况下,我可能会做这样的事情来启用每窗口网格回调:
#include <map>
// this could also be a class with all-static members, if one
// were so inclined. might be worth it, if only to protect 'map'
// from external meddling.
namespace WindowToMesh
{
typedef std::map< int, Mesh * > Map;
Map map;
void addMapping( int win, Mesh * mesh )
{
map.insert( { win, mesh } );
}
void removeMapping( int win )
{
map.erase( win );
}
void draw()
{
int win = glutGetWindow();
Map::iterator it = map.find( win );
if ( it != map.end() )
it.second->draw();
}
} // end namespace WindowToMesh
现在,在您的主程序中,您可以将新的Mesh
与当前窗口关联起来:
Mesh * m = new Mesh( ... );
WindowToMesh::addMapping( glutGetWindow(), m );
您可以将(实际上是静态的(WindowToMesh::draw
函数关联为回调:
glutDisplayFunc( &WindowToMesh::draw );
当你准备销毁Mesh
时,确保你在同一个窗口中,然后:
WindowToMesh::removeMapping( glutGetWindow() );
根据其他因素,进行双向映射可能是有意义的(这样你就可以通过Mesh *
而不仅仅是窗口int
找到东西,或者对罕见的注销进行强力扫描,等等
我没有一个可以测试的环境,但应该很接近。祝你好运
问题是,成员函数指针需要一些信息才能被调用,即要调用的实例,然后this
指针可以在成员函数的实现中访问这些信息,因此您可以访问成员变量。我认为你想这样做,因为你的设计看起来像是你想画Mesh
中定义的东西。
有可能将成员函数指针转换为"正常"函数指针。但您必须记住,一旦调用此函数,这条信息(Mesh
的实例(就必须可用。这意味着从成员函数指针到"正常"函数指针的典型转换会添加参数(实例(。
但是glutDisplayFunc()
接受void(*)(void)
函数指针,即空的参数列表,因此它不会告诉被调用函数任何。您必须确保一旦调用了传递的函数,就可以以任何方式重建"上下文",即Mesh
实例。
这可以通过从代码中的全局点指向Mesh
实例来实现。当您调用我们即将编写的助手函数时,它将始终被使用。因此,当您将指针传递给glutDisplayFunc()
时,一旦我们告诉它应该使用哪个Mesh
,我们的助手函数就会知道该使用哪个。
class Mesh
{
public:
void draw() { ... }
}
Mesh *instance;
// Helper function called by glut:
void display() {
// Now we can access a particular instance:
instance->draw();
}
int main(int argc,char* argv[])
{
Mesh mesh;
// First point to this instance globally:
instance = &mesh;
// Then, pass our helper function which now has an empty parameter list:
glutDisplayFunc(&display);
}
此解决方案有一个限制。不能在不同的实例中重复使用同一个函数指针。因此,不能将任何实例转换为函数指针,而只能为每个全局定义的实例指针转换一个。但由于您只想将draw函数传递给glutDisplayFunc
,因此只需要执行一次,因此应该可以。我只是不想对你隐瞒这种"危险"。(
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 使用指向成员的指针将成员函数作为参数传递
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 修改函数中的指针(将另一个指针作为参数传递)
- 将成员函数指针作为参数传递给模板方法
- 如何在C++中将迭代器作为函数参数传递
- 将附加参数传递给使用 beast::bind_front_handler 调用的函数
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 如何传递带有通过引用传递的结构参数的函数?
- 如何在 c++ 中将函数作为参数传递?
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 将参数打包的参数传递到 std::queue 中,以便稍后使用不同的函数调用
- 为什么我不能将引用作为 std::async 的函数参数传递
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 将__device__ lambda 作为参数传递给 __global__ 函数
- 是否可以在不填充自己的参数的情况下将模板函数作为参数传递?
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 将函数作为参数传递以避免重复代码
- 如何在类(C )中作为参数传递函数