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

C++ には、「クロージャー」と呼ばれる概念がありません。クロージャーは、関数と、関数が実行されるスコープで構成されるタプルです。クラス メンバー関数を使用するには、クラス インスタンスが必要です。C++ にはこの概念がないため、インスタンスのメンバー関数の関数ポインターを取得することはできません。

さらに、GLUT は C API です。つまり、C++ がクロージャをサポートしていたとしても、GLUT はこれをどのように扱うかを知りません。

したがって、インスタンスでクラスメンバー関数を呼び出すために非メンバー関数を使用する必要があります。ほとんどの C API では、コールバック パラメータ (通常は の形式void*) を指定できます。ただし、GLUT はこれを行わないため、事実上、クラスのグローバル インスタンスのみを呼び出すことができます。

アップデート

コードにはさらに問題があります。GUIOpenGL コンテキストが存在する前にインスタンス化します。OpenGL コンテキストは によって作成されglutCreateWindowます。しかし、`GUI' コンストラクターは OpenGL 呼び出しを行いますが、これはコンストラクターが利用できない場合は無効です。

さらに悪いことに、コンストラクター内のすべての呼び出しは、実際には描画コードに属しています。

于 2013-08-31T17:27:22.137 に答える
0
  • エラー メッセージが表示される理由は、関数 display() を GUI クラスのメンバー関数として定義したか、display() 関数を GUI クラスのメンバーとして定義せず、それを呼び出そうとしているためです。 GUI クラス。
  • この問題を解決するには、display() 関数を入力パラメーターのない GUI の非メンバー関数として定義する必要があります。非メンバー関数の場合、この ob.display は実行できません。glutDisplayFunc はメンバー関数を取りません。
  • GUI クラスで非メンバー関数 display() を参照するには、この方法で呼び出す必要があります。
  • glutDisplayFunc(&display);
于 2013-08-31T21:49:29.377 に答える
0

C++ と C は、同じリンケージと ABI を共有していません。さらに、クラスには、「this」ポインターとして知られる「暗黙の」パラメーターと呼ばれるものがあり、引数は隠され、解決されます。内部的には、これにより関数のシグネチャが期待どおりに変更され、コンパイラが詳細を処理して、これが機能することを確認します。C 関数呼び出しは、予期されるシグネチャを持つ関数への参照を予期しています。また、これを直接相互運用する方法はなく、何らかの方法でこれを橋渡しする必要があります。

于 2013-08-31T17:28:28.213 に答える
0

解決

  1. 静的にしdisplayます。
  2. または、GUI クラスを取り除きます。ウィンドウが 1 つしかない場合は、実際には必要ありません。
  3. GUI クラスの単一のグローバル インスタンスをdisplay()作成し、そのメソッドを glut display コールバックから呼び出します。
  4. または、別のライブラリを使用して OpenGL を初期化します。
  5. または、「this」ポインターを glut に渡す方法を見つけてください。

説明

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 に答える