2

Suppose I have some code like this:

class Visitor {
   public:
      Visitor(callBackFunction) {}
      void visit() {
          //do something useful
          invokeCallback();
      }
}

class ClassThatCanBeVisited {
    Visitor &visitor;

    public:
       ClassThatCanBeVisited(Visitor &_visitor) : visitor(_visitor){}
       void someUsefulMethod() {
          int data= 42;
          visitor.visit(data);
       }
};


void callBackFunction() {
    //do something useful in the context of the Main file
}
int main() {
     Visitor visitor;
     ClassThatCanBeVisited foo(visitor);
     foo.someUsefulMethod();
}

I need to create a simple callback that will be called whenever the Visitor::visit() is called. I know that I probably should put the code of the callback inside my Visitor, but it is in a different context, so I would like to pass the callBackFunction() to the Visitor so he could invoke my callback function.

I looked for things on the web and saw boost::function, but c++ already has the basic functors.

Which one should I use for better clarity of the code? The callback is going to be a simple void() function, but it might grow, you never know the future :)

What is the recommended way to do this?

4

3 に答える 3

7

はい、boost::function はこれをうまく行います。それはそれの非常に一般的な使用法です。インスタンスをメンバー関数にバインドするには、boost::bind を使用する必要があります。

 func = boost::bind( &MyClass::CallbackFunc, this);

クラス内からそれを行う方法です。

「これ」が消えないことを確認してください。そうしないと、ブースト関数がどこかのブースト ヘッダーの途中でクラッシュします。

于 2009-03-04T18:43:09.960 に答える
4

boost::function を使用したくない場合は、コールバック インターフェイスとその階層を使用できます。

class VisitorCallback
{
public:
    virtual void handle( const Visitor& ) = 0;
};

boost::function を持っている、または使用できる場合は、それを使用してください。これは、これらすべてのコールバック クラスを取り除く良い方法です。

編集:
@edisongustavo:

boost::function と boost::bind は、おそらくコードを読みやすくすることはありません。ただし、無料の関数(クラス外の関数と静的クラス関数を意味します)をコールバックとして、および任意のクラスの既存の関数として渡す機会が与えられます。

ブースト関数を使用すると、たとえば 2 つのパラメーターを持つ関数をコールバックとして渡すことができますが、パラメーターは 1 つしか必要ありません。

typedef boost::function< void ( int ) > IntExpectingCallback;

void TwoIntFunction( int, int );
{
}
...
IntExpectingCallback callback = boost::bind( TwoIntFunction, 5, _1 );

ただし、繰り返しますが、チーム全員がブーストを知っていて支持しない限り、コードが読みやすくなることはありません。

于 2009-03-04T18:45:37.130 に答える
1

上記の回答は素晴らしいですが、質問で言及したことを指摘したいと思います。これは、C ++コールバックオブジェクト(Mykolaの回答)とブーストのどちらを選択するかに関連しています。

「コールバックは単純なvoid()関数になりますが、大きくなる可能性があります。将来はわかりません:)」

これはおそらく、余分な不要な機能の最悪の理由です。つまり、「必要な場合に備えて」です。わからない場合は、必要以上のことをしないでください。とにかく、特に必要なときまでに、推測が間違っている可能性があります。

一方、機能がすぐに必要になる可能性が非常に高いことがわかっている場合は、追加する価値があるかもしれません。

もう一度、Mykolaが言ったことを繰り返します。プロジェクトにすでにブーストがあり、チームがそれを気に入っている場合は、それを使用しますが、そうでない場合はやり過ぎかもしれません。

于 2009-04-23T07:28:13.437 に答える