1

私はこれをできるだけ明確に説明するために最善を尽くします。

私の例には現在、3 つの異なるクラスが含まれています。

  1. 私のモデルクラス(それを呼びましょうMyModel.cpp
  2. MyModel が ( MyData.cpp)のオブジェクトを持つ私のデータ クラス
  3. モデルを変更する undo redo クラス ( MyModelUR.cpp)

MyModelオブジェクトを持っていMyDataます。 MyDataそれぞれ独自の get および set 関数を持つ double の束が含まれています。私のシステムの仕組みは、セッターが を呼び出すことによって呼び出されることredo()ですMyModelUR。このredo()関数はMyModel、変更が検出されたときに呼び出されます。ただし、これは問題の範囲外です。

MyModelURいくつかの引数を取り、引数を取ることを許可されていundo()ないコンストラクターの 3 つの関数があります。redo()

MyModel何が起こるかというと、目的のセッターの関数ポインターを に渡したいのMyDataですMyModelUR

したがって、コンストラクターはMyModelUR関数ポインターを引数として受け取り、それをプライベートグローバル変数に格納する必要があることを意味します。これまでのところ、私はこのようなものを持っています...

MyModelUR::MyModelUR(MyModel* model, double newValue, void (*function)(double))
{
    Model = model;

    NewValue = newValue;

    //FunctionToCall is a void*
    FunctionToCall = &function;
}

今、私のredo()関数で使用したいFunctionToCall...これをやろうとしていますが、うまくいかず、コンパイルエラーが発生するだけです...

MyModelUR::redo()
{
    Model->data()->FunctionToCall(NewValue);
}

このように実装したいので、ダブルインごとに X 個のundo()/関数は必要ありません。redo()MyData

あなたの助けと提案に感謝しますが、他の制約のためにこのアーキテクチャを使用したい、Boost ライブラリを使用できないなどの返信を検討する際に、いくつかの制限があります。

TLDR; オブジェクトで呼び出されている別のクラスで double を取る void 関数ポインターを呼び出したいです。

ありがとうございました!

編集:以下のコメントの後、これは私が取り組んでいるものです...

MyModelUR::MyModelUR(MyModel* model, double newValue, void (MyModel::*function)(double)) :
    Model(model),
    NewValue(newValue),
    FunctionToCall(function)
{
}

void MyModelUR::redo()
{
    MyData data = Model->data();

    data.*FunctionToCall(NewValue);
}

ただし、これにより、コードの 2 行目で次のようなエラーがスローさredo()ます。

4

1 に答える 1

1

まず、関数ポインターはメソッドポインターである必要があり、自由関数ポインターを使用しようとしています。

次に、これをとして保存しようとしないでくださいvoid*。同じサイズであることが保証されているわけではありません。メソッドポインタとして宣言し、キャストを停止するだけです。

最後に、現在、一時関数ポインタ引数のアドレスvoid*を(に)格納しています。これは、正しい型であっても無効になります。

コードは次のようになります。

class MyModelUR {
    ...
    MyModel *Model;
    double NewValue;
    void (MyData::*FunctionToCall)(double);
    ...
    MyModelUR(MyModel* model, double newValue, void (MyData::*function)(double))
      : Model(model), NewValue(newValue), FunctionToCall(function)
    {}
    void redo() {
        MyData &data = Model->data();
        (data.*FunctionToCall)(NewValue);
    }
};

次のようなもののいずれかをインスタンス化します。

MyModelUR *ur = new MyModelUR(model, 3.4, &MyData::setSomeValue);

機能上の注意:元に戻す場合は、getterメソッドポインタと古い値を格納する場所が必要になります。

美的注意:最初の大文字のメンバー名はひどいものです。これは、型に使用しているのと同じスキームです。ただIMO。

于 2013-01-04T14:03:12.620 に答える