Ошибка C2664 при попытке сделать некоторые OpenGl в C ++ - PullRequest
0 голосов
/ 09 октября 2009

Вот резюме моего кода. Я пытаюсь использовать glutSpecialFunc, чтобы сообщить glut использовать мою функцию KeyPress

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

Ответы [ 2 ]

2 голосов
/ 09 октября 2009

Ваша функция является членом класса. Когда вы делаете что-то вроде Car c; c.drive(), для этой функции drive() нужен автомобиль для работы. Это указатель this. Так что перенасыщение не может вызвать эту функцию, если у нее нет машины для работы, она ожидает бесплатную функцию.

Вы могли бы сделать свою функцию 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)
    {
        // ...
    }
};

Конечно, не стесняйтесь задавать больше вопросов, если это не имеет смысла.

0 голосов
/ 09 октября 2009

То, что я закончил, было

Добавление:

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++;
        }
    }
...