0

以下是绘制矩形的代码,但在 glutdisplayFunc() 中出现错误。我该如何解决?

#include <iostream>
#include <glut.h>

using namespace std;

class GUI
{
  public:
    int W,H;
    GUI()
    {
        W = 800;
        H = 600;
        glClearColor(0, 0, 0, 0);
        gluOrtho2D(-W, W, -H, H);
        glMatrixMode(GL_PROJECTION);
    }
    void display()
    {
        glBegin(GL_POLYGON);
        glVertex2d(-500, 300);
        glVertex2d(500, 300);
        glVertex2d(500, -300);
        glVertex2d(-500, -300);
        glEnd();
        glFlush();
    }
};

int main(int argv, char **argc)
{
    GUI ob;

    glutInit(&argv, argc);
    glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
    glutInitWindowSize(ob.W, ob.H);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Queen Problem");
    glutDisplayFunc(ob.display);      //Error
    glutMainLoop();
    return 0;
}

我正在使用Visual Studio 2010我在OpenGL中创建了一些程序,但没有任何类。这是我在 OpenGL 中使用类的第一次体验。

错误是:

错误 1 ​​错误 C3867: 'GUI::display': 函数调用缺少参数列表;使用 '&GUI::display' 创建指向成员的指针。

我尝试使用&GUI::display,但它也导致了错误。

4

4 回答 4

0
  • The reason why you are getting the error message is because you either defined the function display() as a member function of GUI class or you did not defined the display() function as a member of GUI class and you are trying to call it from the GUI class.
  • To fix the problem, you need to define display() function as a non-member function of GUI with no input parameters. If it`s a non-member function you cannot do this ob.display. glutDisplayFunc does not take a member function.
  • To refer to the non-member function display() on GUI class, you need to call it this way;
  • glutDisplayFunc(&display);
于 2013-08-31T21:49:29.377 回答
0

C++没有称为“闭包”的概念。闭包是一个元组,由一个函数和一个执行函数的作用域组成。类成员函数需要一个类实例才能使用。由于 C++ 中缺少此概念,因此您不能获取实例成员函数的函数指针。

此外,GLUT 是一个 C API,这意味着即使 C++ 确实支持闭包,GLUT 也不知道如何使用它。

因此,您必须使用非成员函数来调用实例上的类成员函数。大多数 C API 允许您提供回调参数(通常以 a 的形式void*)。然而,GLUT 并没有这样做,因此您只能调用该类的全局实例。

更新

您的代码还有其他问题。GUI您在 OpenGL 上下文之前实例化。OpenGL 上下文由glutCreateWindow. 但是“GUI”构造函数会进行 OpenGL 调用,如果没有可用的构造函数,这些调用是无效的。

更糟糕的是:构造函数中的所有调用实际上都属于绘图代码。

于 2013-08-31T17:27:22.137 回答
0

解决方案

  1. display静态的。
  2. 或者摆脱 GUI 类。如果你只有一个窗口,你真的不需要它。
  3. 制作 GUI 类的单个全局实例,并display()从 glut 显示回调中调用其方法。
  4. 或者使用不同的库来初始化 OpenGL。
  5. 或者找到一种方法通过 glut 传递“this”指针。

解释

在 C++ 中,类方法具有隐藏this参数,除非它是静态的。this没有指针就不能调用非静态类成员。

GLUT 需要一个没有this参数的函数。

如果你不知道this" 指针是什么,你需要买一本 C++ 的书,多学习。

要么使“显示”静态(在这种情况下,您将无法从方法中访问类成员),或者找到某种方法来传递“this”指针以在其中使用。

通过 glut传递this指针并将调用转发给类将如下所示:

class Gui{
public:
    void display();
};

void* getWindowData(int id);
void setWindowData(int id, void* p);

void displayForwarded(){
    Gui *gui = (Gui*)getWindowData();      
    if (gui)
        gui->display();
}

int main(int argc, char** argv){
    ....
    int windowId = glutCreateWindow();       
    Gui gui;
    setWindowData(windowId, &gui);
    glutDisplayFunc(displayForwarder);
}

问题是getWindowData()和的内容setWindowData()。如果您使用的是 OpenGLUT,则可以glutSetWindowData在其中使用函数。

在 FreeGLUT 中,您可以滥用窗口标题来通过它传递一个指针(坏主意,不要那样做),但这是一种不好的品味。

所以剩下的就是创建一个全局映射,它将窗口 ID 转换为用户数据指针和用户数据。

typedef int WindowId;
typedef std::map<WindowId, Gui*> GuiMap;

namespace Internal{
     GuiMap guiMap;
}
class Gui{
public:
    ...
    void display();
}

void setWindowGui(WindowId id, Gui* p){
     Inertnal::guiMap[id] = p; // guiMap.insert(std::make_pair(id, p))
}

Gui* getWindowGui(WindowId id){
     GuiMap::iterator found = Internal.guiMap.find(id);
     if (found == Internal.guiMap.end())
         return 0;
     return found.second;
}

void displayForwarder(){
     WindowId = getGetWindow();//glut function
     Gui *gui = getWindowGui(id);
     if (!gui)
         throw std::string("gui not found");
     gui->display();
}

int main(int argc, char** argv){
    ...
    Gui gui;
    WindowId window = glutCreateWindow(.....);...
    setWindowGuiwindow, &gui);
    glutDisplayFunc(displayForwarder);
    ...
    ...
}

如果您不理解答案,请获取 C++ 书籍并阅读它。

于 2013-08-31T22:20:13.127 回答
0

C++ 和 C 不共享相同的链接和 ABI。此外,对于类,有一个称为“this”指针的“隐式”参数,该参数被隐藏并为您解析。在内部,这将改变您所期望的函数签名,编译器会处理确保其工作的细节。C 函数调用需要对具有预期签名的函数的引用。它也无法直接进行互操作,您必须以某种方式桥接它。

于 2013-08-31T17:28:28.213 回答