2

私はC++の関数ポインタの概念にかなり慣れていないので、質問を適切に書く方法がわかりません. 我慢してください。

基本的に、私がやろうとしているのは、コンストラクターが関数ポインターをパラメーターとして受け入れる Button オブジェクトを作成することです。その関数ポインタは、StateMachine の状態を変更する関数を指しています。

サンプル コードは次のとおりです (動作せず、無関係なビットが取り除かれています)。

ボタン.h

#include "StateMachine.h"

class Button
{
private:   
    void (*m_onclickAction)();    //a data member
public:
    Button(void (*action)());
};

StateMachine.h (私が書いたのではなく、許可を得て使用しているだけです。したがって、コードに問題はないはずであり、変更したくありません)

#include <map>

template<class E, class T>
class StateMachine
{
public:
    typedef void (T::*CallbackOnInitialise)();
    typedef void (T::*CallbackOnExit)();
private:    
    T* m_pOwner;
    E m_currentState;

    // Maps to store function pointers to state functions.
    std::map<E, CallbackOnInitialise> m_statesOnInitialise;
    std::map<E, CallbackOnExit> m_statesOnExit;

public:
    StateMachine(T* pOwner, E emptyState)
    {
        m_currentState = emptyState;
        m_pOwner = pOwner;
    }

    void ChangeState(E statenext)
    {
        //do something to change the state
    }
};

メインの Program クラスで、次のようなことができるように

#include "Button.h"
#include "StateMachine.h"

//Code to instantiate an StateMachine object goes here
Button* aButton = new Button(aStateMachine->ChangeState(NEW_STATE));

問題は、関数ポインターがパラメーターを想定していないため、Program クラスで宣言された列挙型である NEW_STATE を正しく渡す方法が思いつかないことです。私はそれを微調整しようとしましたが、成功しませんでした。

どうすればいいですか?

4

3 に答える 3

0

ライブラリには設計上のバグがあります。

問題は、関数ポインターが C++ の単なる関数ポインター (クロージャーではない) であるため、コンテキストがないことです。

青い円を描くボタンを作成したい場合は、パラメータを取らずに青い円を描くグローバル関数が必要です。

別のボタンで黄色の円を描画する場合は、パラメーターを取らずに黄色の円を描画する別のグローバル関数が必要になります。

より具体的には、ライブラリには、円を描くために使用する色をコードに渡すことができる「コンテキスト」と呼ばれるものをボタンに保存する方法がないことです。

C++11 は少しクロージャを思い出させる何かを追加しました (ガベージ コレクションなしではどの言語でも解決するのが難しい寿命の問題のため、実際のものではありません) が、それらは裸の関数ポインタではありません。

あなたがやりたいことは、クラスを変更せずに不可能です。ここで見ることができるButtonような悪いハックを使用しない限り、裸の関数ポインターを使用して C でエミュレートしようとします。std::bind

于 2013-10-04T06:15:33.750 に答える