4

こんにちは。私は経験豊富な c# プログラマーで、c++ でいくつかの作業を行おうとしていますが、これを行う正しい方法がわかりません。

何かが起こったことを消費クラスに通知する必要があるクラスを作成しています。

これを C# で記述している場合は、クラスでイベントを定義します。

C ++にはイベントがないため、これを行う正しい方法を見つけようとしています。コールバック関数は考えましたが、メンバー関数(静的関数ではない)を実行したい場合はどうすればよいですか。

より具体的には、私が実際に行う必要があるのは、イベントを処理することですが、イベントを処理しているオブジェクト インスタンス内のメンバー状態にアクセスできるようにすることです。

std::tr1:function を見てきましたが、うまく動作しません。

次の例の c# の例を正しい/ベスト プラクティスの c++ の例に変換したいと思う人はいないと思います (ANSI c++ が必要です)。(私は C++ の経験がほとんどないことを覚えておいてください -- 私が長い間確立された C++ の慣習を知っていると仮定しないでください -- 私は知りません ;);

シンプルな c# コンソール アプリ (私のマシンで動作します):


using System;

namespace ConsoleApplication1
{
    public class EventSource
    {
        public event EventHandler<EchoEventArgs> EchoEvent;

        public void RaiseEvent(int echoId)
        {
            var echoEvent = this.EchoEvent;
            if (echoEvent != null)
                echoEvent(this, new EchoEventArgs() {EchoId = echoId});
        }
    }

    public class EchoEventArgs : EventArgs
    {
        public int EchoId { get; set; }
    }

    public class EventConsumer
    {
        public int Id { get; set; }
        public EventConsumer(EventSource source)
        {
            source.EchoEvent += OnEcho;
        }

        private void OnEcho(object sender, EchoEventArgs args)
        {
            // handle the echo, and use this.Id to prove that the correct instance data is present.
            Console.WriteLine("Echo!  My Id: {0}  Echo Id: {1}", this.Id, args.EchoId);
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var source = new EventSource();
            var consumer1 = new EventConsumer(source) { Id = 1 };
            var consumer2 = new EventConsumer(source) { Id = 2 };
            source.RaiseEvent(1);
            Console.ReadLine();
        }
    }
}

4

4 に答える 4

3

std::function<Signature>基本的な考え方は、たとえばコールバックのような関数オブジェクトを取得することです。これらは関数ポインタではありませんが、呼び出すことができます。標準C++ライブラリ(C ++ 2011用)には、たとえば、メンバー関数を含む関数を関数オブジェクトとして使用できるようにする、いくつかのクラスと関数が含まれてstd::mem_fn()std::bind()ます。

欠落している部分は、登録される複数のイベントをサポートするものですstd::function<Signature>。1つの機能を表します。ただし、それらをたとえばに入れるのは簡単std::vector<std::function<Signature>>です。さらに興味深いのは(そして可変個引数テンプレートを簡単に実行する必要がある)、複数のイベントの抽象化をカプセル化するイベントクラスを作成することです。

于 2012-10-05T22:30:51.957 に答える
1

C ++には、呼び出し可能なオブジェクトであるファンクターの概念があります。あなたはそれらについて読む必要があります。

を上書きしたオブジェクトについて考えてみてくださいoperator()。そのようなオブジェクトのインスタンスを渡します。その後、通常の関数のように呼び出すことができます。そしてそれは状態を維持することができます。

于 2012-10-05T22:29:06.287 に答える
1

Qt には Signals and Slots と呼ばれるものがあります: http://qt-project.org/doc/qt-4.8/signalsandslots.html

オブジェクトが持つシグナル (リッスンするイベント) とスロット (受信側) を指定して、それらを接続できます。あなたが必要だと述べたように、複数のオブジェクトが信号をリッスンできます。

Qt は大きなアプリ フレームワークなので、シグナルとスロットの部分だけを使用する方法がわかりません。しかし、GUI アプリケーション全体を構築している場合は、Qt の残りの部分も役立つ可能性があります (UI イベントの多くはシグナルとスロットに基づいています)。

于 2012-10-06T00:39:50.623 に答える
1

Boost にはSignals2ライブラリもあり、少なくとも慣用的な意味で、実際の C# イベントに非常に近い API を提供します。

于 2012-10-05T23:03:20.377 に答える