如何传递成员函数指针?

时间:2015-01-09 17:06:28

标签: pointers opengl c++11

我为openGl操作创建了一个类。现在,过度回调函数需要函数的指针作为参数。我通过实例化类的对象来提供成员函数。它显示了像

这样的错误
main.cpp: In function ‘int main(int, char**)’:
main.cpp:23:64: error: cannot convert ‘std::_Bind_helper<false, void (glActivity::*)(), glActivity*>::type {aka std::_Bind<std::_Mem_fn<void (glActivity::*)()>(glActivity*)>}’ to ‘void (*)()’ for argument ‘1’ to ‘void glutDisplayFunc(void (*)())’
     glutDisplayFunc(std::bind(&glActivity::display,&GLactivity));
main.cpp:24:51: error: cannot convert ‘GlActivity::reshape’ from type ‘void (GlActivity::)(int, int)’ to type ‘void (*)(int, int)’
     glutReshapeFunc(GLactivity.GlActivity::reshape);

头文件的代码在这里:

#include<GL/freeglut.h>
#include<GL/gl.h>
class GlActivity{
protected:
    bool keys[256];
public:
    /*Initialize material property,light source,lighting model
     *and depth buffer through the constructor call.
     */
    GlActivity(){
    glShadeModel(GL_FLAT);
    //glEnable(GL_LIGHTING);
    //glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
    void Keydown(unsigned char ch,int x,int y){
        if(ch == 27) glutExit();
        keys[ch]=true;
    }
    void keyup(unsigned char ch,int x,int y){
        keys[ch]=false;
    }
    void display(void){
    }
    void reshape( int w,int h){
        glViewport(0,0,(GLsizei) w,(GLsizei) h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        if(w <= h)
            glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w,
            1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0);
        else
            glOrtho(-1.5,1.5,-1.5*(GLfloat)w/(GLfloat)h,
            1.5*(GLfloat)w/(GLfloat)h,-10.0,10.0);
            glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }
    void idle(){}
};

和main.cpp的那个是:

#include"matrix.h"
#include"GlActivity.h"
#include <functional>
class glActivity : public GlActivity{
public:
    glActivity():GlActivity(){}
    void display(){
        glBegin(GL_TRIANGLES);
            glVertex2f(0.0f,1.0f);
            glVertex2f(0.87f,-0.5f);
            glVertex2f(-0.87f,-0.5f);
        glEnd();
        glFlush();
    }
};
int main(int argc,char** argv){
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(100,100);
    glutCreateWindow(argv[0]);
    glActivity GLactivity;
    glutDisplayFunc(std::bind(&glActivity::display,&GLactivity));
    glutReshapeFunc(GLactivity.GlActivity::reshape);
    glutKeyboardFunc(GLactivity.GlActivity::keydown);
    glutKeyboardFunc(GLactivity.GlActivity::keyup);
    glutIdleFunc(GLactivity.GlActivity::idle);
    glutMainLoop();
    return 0;
}

2 个答案:

答案 0 :(得分:0)

问题就在这一行我猜:

glutDisplayFunc(std::bind(&glActivity::display,&GLactivity));

问题是glutDisplayFunc是一个C函数,std::bind返回一个C ++对象,这是任何C函数都无法处理的。

您必须提供C函数可以处理的内容,例如纯函数指针或非捕获lambda。

答案 1 :(得分:0)

GLUT不会让你这么容易,但如果你理解GLUT调用回调时存在的条件,就有可能。

大多数基于C的API允许您为用户数据传递void*,并允许您通过强制转换到适当的接口,将基于C的回调分派给C ++类的实例。 GLUT不这样做,绝对没有特定于实例的信息传递给你的回调。

但是,当GLUT调用回调时,它会使用已建立的&#34;当前窗口&#34; 进行回调。您可以通过调用glutGetWindow (...)手动查询当前窗口,然后使用它。

所以你可能会考虑这样的事情:

glActivity* windows [2];

void glut_display_callback (void)
{
  windows [glutGetWindow ()]->display ();
}

你会想要在现实世界中使用比数组更复杂的东西,因为窗口ID甚至不是从GLUT中的 0 开始,但这给你一般的想法。