2009-10-08 54 views
0

這裏是我的代碼的一個摘要。我試圖用glutSpecialFunc告訴供過於求用我的按鍵響應功能嘗試在C++中做一些O​​penGl的C2664錯誤

class Car : public WorldObject 
{ 
public: 
void KeyPress(int key, int x, int y) 
{ 
} 

Car() 
{ 
    glutSpecialFunc(&Car::KeyPress); // C2664 error 
} 
} 

該錯誤消息我得到的是:

Error 1 error C2664: 'glutSpecialFunc' : cannot convert parameter 1 from 'void (__thiscall Car::*)(int,int,int)' to 'void (__cdecl *)(int,int,int)' c:\users\thorgeir\desktop\programmingproject1\quickness\quickness\car.cpp 18 Quickness 
+0

這個問題應該被重新標記爲Visual Studio或Visual-C++ – 2009-10-08 23:45:17

回答

2

你的函數是一個類的成員。當你做一些像Car c; c.drive()這樣的功能時,那drive()功能需要一輛車來使用。這是this指針。所以如果沒有汽車可以使用,那麼glut就不能調用這個函數,它需要一個自由函數。

你可以使你的功能static,這意味着功能不能在汽車上運行。然後過剩可以稱爲它,但我認爲你想操縱一輛汽車。解決的辦法是使函數傳遞給它的呼叫到一個對象,像這樣:

void key_press(int key, int x, int y) 
{ 
    activeCar->KeyPress(key, x, y); 
} 

哪裏activeCar是一些全局訪問指針車。你可以用一些CarManager單身做到這一點。

CarManager記錄正在控制的活動汽車,所以當按下某個按鍵時,您可以通過它:CarManager::reference().active_car().KeyPress(key, x, y)

單例是一個對象,它只有一個全局可訪問的實例。它不在答案的範圍內,但您可以通過Google獲取各種資源來創建一個。查找邁爾斯辛格爾頓爲一個簡單的單身解決方案。

另一種方法是擁有一種InputManager單例,並且該管理器將跟蹤它應該通知按鍵的對象列表。這可以通過幾種方法來完成,最簡單的將是這樣的:

class InputListener; 

class InputManager 
{ 
public: 
    // ... 

    void register_listener(InputListener *listener) 
    { 
     _listeners.push_back(listener); 
    } 

    void unregister_listener(InputListener *listener) 
    { 
     _listeners.erase(std::find(_listeners.begin(), _listeners.end(), listener)); 
    } 

    // ... 

private: 
    // types 
    typedef std::vector<InputListener*> container;   

    // global KeyPress function, you can register this in the constructor 
    // of InputManager, by calling glutSpecialFunc 
    static void KeyPress(int key, int x, int y) 
    { 
     // singleton method to get a reference to the instance 
     reference().handle_key_press(key, x, y); 
    } 

    void handle_key_press(int key, int x, int y) const 
    { 
     for (container::const_iterator iter = _listeners.begin(); 
      iter != _listenders.end(), ++iter) 
     { 
      iter->KeyPress(key, x, y); 
     } 
    } 

    container _listeners; 
}; 

class InputListener 
{ 
public: 
    // creation 
    InputListener(void) 
    { 
     // automatically add to manager 
     InputManager::reference().register_listener(this); 
    } 

    virtual ~InputListener(void) 
    { 
     // unregister 
     InputManager::reference().unregister_listener(this); 
    } 

    // this will be implemented to handle input 
    virtual void KeyPress(int key, int x, int y) = 0; 
}; 

class Car : public InputListener 
{ 
    // implement input handler 
    void KeyPress(int key, int x, int y) 
    { 
     // ... 
    } 
}; 

當然隨時問更多的問題,如果這沒有意義。

+1

哇很好的答案,非常快!解釋一切。 – Thorgeir 2009-10-08 23:25:39

0

我最終什麼事做了

添加:

virtual void KeyPress(int key, int x, int y) {}; 

到WorldObject類

和氣泡事件的車。

void KeyPressed(int key, int x, int y) 
    { 
     KeyPress(key,x,y); 

     list<WorldObject*>::iterator iterator = ChildObjects.begin(); 
     while(iterator != ChildObjects.end()) 
     { 
      (*iterator)->KeyPressed(key,x,y); 
      iterator++; 
     } 
    }