尝试在c ++中执行一些OpenGl时出现C2664错误

时间:2009-10-08 22:27:36

标签: c++ opengl glut c2664

这是我的代码摘要。我正在尝试使用glutSpecialFunc告诉过剩使用我的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 个答案:

答案 0 :(得分:2)

您的函数是类的成员。当您执行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上创建各种资源。查看Meyers Singleton的简单单例解决方案。

另一种方法是使用一种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 :(得分: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++;
        }
    }