0

これが私のコードの要約です。glutSpecialFuncを使用して、KeyPress関数を使用するようにglutに指示しようとしています。

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
4

2 に答える 2

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)

シングルトンは、グローバルにアクセス可能なインスタンスが1つしかないオブジェクトです。それは答えの範囲外ですが、それを作成するためのさまざまなリソースをグーグルで検索できます。単純なシングルトンソリューションについては、MeyersSingletonを検索してください。

別のアプローチは、一種の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)
    {
        // ...
    }
};

もちろん、これが意味をなさない場合は、さらに質問してください。

于 2009-10-08T22:32:37.180 に答える
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++;
        }
    }
于 2009-10-08T23:26:22.360 に答える