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

发布于 2024-08-07 08:51:37 字数 527 浏览 7 评论 0原文

这是我的代码的摘要。我正在尝试使用 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

Here is an abstract of my code. I'm trying to use glutSpecialFunc to tell glut to use my KeyPress function

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

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

The error message I get is:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寂寞笑我太脆弱 2024-08-14 08:51:37

你的函数是一个类的成员。当你做类似 Car c; 的事情时c.drive(),该 drive() 函数需要一辆汽车才能使用。这就是 this 指针。因此,如果 glut 没有汽车可以使用,则它无法调用该函数,它需要一个免费函数。

您可以将函数设置为静态,这意味着该函数无法在汽车上运行。然后 glut 就可以调用它,但是我假设你想操纵一辆汽车。解决方案是让函数将其调用传递给一个对象,如下所示:

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)
    {
        // ...
    }
};

当然,如果这没有意义,请随意提出更多问题。

Your function is a member of a class. When you do something like Car c; c.drive(), that drive() function needs a car to work with. That is the this pointer. So glut can't call that function if it doesn't have a car to work on, it's expecting a free function.

You could make your function static, which would mean the function does not operate on a car. glut will then be able to call it, however I assume you want to manipulate a car. The solution is to make the function pass it's call onto an object, like this:

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

Where activeCar is some globally accessible pointer to car. You can do this with some sort of CarManager singleton.

CarManager keeps track of the active car being controlled, so when a key is pressed you can pass it on: CarManager::reference().active_car().KeyPress(key, x, y).

A singleton is an object that has only one globally accessible instance. It is outside the scope of the answer, but you can Google for various resources on creating one. Look up Meyers Singleton for a simple singleton solution.

A different approach is to have a sort of InputManager singleton, and this manager will keep track of a list of objects it should notify of key presses. This can be done in a few ways, the easiest would be something like this:

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)
    {
        // ...
    }
};

Of course feel free to ask more questions if this doesn't make sense.

情何以堪。 2024-08-14 08:51:37

我最终做的是

添加:

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

到 WorldObject 类

并将事件冒泡到 Car。

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

What I ended up doing was

Adding:

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

to the WorldObject class

And bubble the event to the Car.

    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++;
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文