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>代表一个功能。但是,很容易将它们放入,例如,放入std::vector<std::function<Signature>>. 变得更有趣(并且需要可变参数模板轻松完成)是创建一个事件类,该类封装了多个事件的抽象,这些事件开始注册、可能未注册和调用。

于 2012-10-05T22:30:51.957 回答
1

C++ 有一个函子的概念:一个可调用的对象。你需要阅读它们。

考虑一个已覆盖的对象operator()。你传递这样一个对象的一个​​实例。之后,您可以像调用常规函数一样调用它。并且可以保持一个状态。

于 2012-10-05T22:29:06.287 回答
1

Boost 中还有Signals2库,它提供了一个非常接近真实 C# 事件的 API,至少在惯用意义上。

于 2012-10-05T23:03:20.377 回答
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 回答