4

一部の C# コードを C++ に変換中です。私は最初、デリゲートを C スタイルのコールバックに置き換えることを考えていました。ただし、コードをさらに調べたところ、次のような (疑似 C# コード) ステートメントを使用して、デリゲートがマルチキャスト方式で使用されているため、これは機能しないことがわかりました。

DelegateTypeOne one = new DelegateTypeOne(someCallbackFunc1)
one += new DelegateTypeOne(someCallbackFunc2)

移植されるコードがデリゲートを単一のキャスト方式で使用する場合、通常の C スタイルの関数ポインターを使用することでうまくいく可能性があることを理解しています。その点について、1 つ質問があります。次の C++ コードは有効ですか?:

typedef std::vector<int> (CallbackTypeOne*) (const std::string& s, const bool b);
std::vector<int> foo (const std::string& s, const bool b);

CallbackTypeOne func_ptr = NULL;

func_ptr =  new CallbackTypeOne(foo);  // Note: new being used on a typedef not a type

// or should I just assign the func the normal way?
func_ptr =  foo;   // this is what I am doing at the moment

デリゲートの実装に関する私の最初のアイデアは、ファンクターとなるデリゲートと呼ばれる ABC を作成することでした。他のすべてのデリゲートはこの ABC から派生し、STL コンテナー (ほとんどの場合、リスト) を持ちます。このコンテナーには、割り当てられた関数のリストが含まれ、順番に呼び出されます。

これはかなりの作業のようであり、最適なアプローチであるとは確信していません。この種の C# から C++ への変換を以前に行った人はいますか? C++ でマルチキャスト デリゲートを実装するための推奨される方法は何ですか?

4

3 に答える 3

5

考えられる解決策が 2 つあります

  1. 関数ポインターの代わりに、関数ポインターのベクトルを使用します。コールバックのベクトルを保持し、呼び出されたときにコールバックを呼び出す operator() を持つクラスを定義します
  2. ブースト信号を使用する
于 2013-01-13T12:18:44.520 に答える
4

このマルチキャスト デリゲートの例を試してください。C++11 => gcc 4.7 以降を想定しています。

////////////////////////////////////////////////////////////
//
//      Bind and Function
//
////////////////////////////////////////////////////////////

#include <vector>
#include <string>
#include <iostream>
#include <functional>
using namespace std;


class Greeting
{
public:
    Greeting(const string& name) : name(name) {}
    string Hello() { return "Hello " + name; }
    string Wait() { return "Wait " + name; }
    string Goodbye() { return "Goodbye " + name; }
private:
    string name;
};

template <typename T>
struct Delegate
{
    vector<T> list;

    void operator+=(T item)
    {
        list.push_back(item);
    }

    void operator() ()
    {
        for(unsigned i = 0; i < list.size(); i++)
        {
            T item;
            item = list[i];
            cout << item() << endl;
        }
    }
};


//////

int main()
{
    // create pointer to function objects
    function<string()> f;
    Delegate<function<string()>> d;
    Greeting john("John");
    Greeting sue("Sue");

    // load up multicast delegate
    d += bind(&Greeting::Hello, john);
    d += bind(&Greeting::Goodbye, sue);
    d += bind(&Greeting::Wait, john);

    // fire delegate
    d();

    return 0;
}
于 2013-10-14T22:02:49.990 に答える
0

最も単純なアプローチは、たとえばstd::vector< std::function<TSignature> >マルチキャストデリゲートのバッキング構造として使用することです。ただし、std::function呼び出し可能な型のラッパーとして使用しても、詳細がかなり厄介になる可能性があるため、boost::signals...を使用することをお勧めします。

于 2013-01-13T14:11:58.887 に答える