C2664 de error en un intento de hacer un poco de OpenGL en C ++
Pregunta
Este es un resumen de mi código. Estoy tratando de utilizar glutSpecialFunc para contar superabundancia de usar mi función KeyPress
class Car : public WorldObject
{
public:
void KeyPress(int key, int x, int y)
{
}
Car()
{
glutSpecialFunc(&Car::KeyPress); // C2664 error
}
}
El mensaje de error que consigo es:
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
Solución
Su función es un miembro de una clase. Cuando haces algo como Car c; c.drive()
, esa función drive()
necesita un coche para trabajar. Ese es el puntero this
. Así exceso no puede llamar a esa función si no tiene un coche para trabajar, que está esperando una función libre.
Se podría hacer su static
función, lo que significaría la función no opera en un coche. exceso será entonces capaz de llamarlo, sin embargo supongo que desea manipular un coche. La solución es hacer que la función de llamada de pasarlo a un objeto, como esto:
void key_press(int key, int x, int y)
{
activeCar->KeyPress(key, x, y);
}
Cuando activeCar
algún puntero globalmente accesible a coche. Usted puede hacer esto con algún tipo de Singleton CarManager
.
CARMANAGER no pierde de vista el coche activo que se está controlado, por lo que cuando se pulsa una tecla que puede transmitirlo:. CarManager::reference().active_car().KeyPress(key, x, y)
A singleton es un objeto que tiene sólo una instancia accesible a nivel mundial. Está fuera del alcance de la respuesta, pero se puede buscar en Google para los diversos recursos en la creación de una. Busque Meyers Singleton Singleton para una solución sencilla.
Un enfoque diferente es tener una especie de InputManager Singleton, y este gerente mantendrá un registro de una lista de objetos, lo notificará de pulsaciones de teclas. Esto se puede hacer de varias maneras, lo más fácil sería algo como esto:
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)
{
// ...
}
};
Por supuesto, no dude en hacer más preguntas si esto no tiene sentido.
Otros consejos
Lo que terminé haciendo fue
Adición:
virtual void KeyPress(int key, int x, int y) {};
para la clase WorldObject
Y la burbuja del evento para el coche.
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++;
}
}