Reputation: 21751
Hi all: I'm an experienced c# programmer trying to do some work in c++, and I'm not sure about the right way to do this:
I am authoring a class that needs to notify a consuming class that something has happened.
If I were writing this in c#, I would define an event on my class.
No events in c++, so I am trying to figure out what is the correct way to do this. I have thought about callback functions, but how do I handle a case where I want to execute a member function (not a static function).
More specifically, what I really need to do is to handle the event, but have access to member state within the object instance that is handling the event.
I have been looking at std::tr1:function, but I am having trouble getting it to work.
I don't suppose that anyone would want to translate the following example c# example into an example of the correct/best practice c++ (I need ANSI c++)? (please bear in mind that I have almost no c++ experience -- don't assume that I know any long-established c++ conventions -- I don't ;);
A simple c# console app (works on my machine):
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();
}
}
}
Upvotes: 4
Views: 192
Reputation: 3248
Qt has something that might help you called Signals and Slots: http://qt-project.org/doc/qt-4.8/signalsandslots.html
It lets you specify what the signals (the events that you want to listen to) and the slots (the receiving side) an object has, and then you can connect them. More than one object can listen to a signal like you mention you needed.
Qt is a large app framework, so I'm not sure how to use only the signals & slots part of it. But if you're building an entire GUI application the rest of the Qt might benefit you too (a lot of the ui event stuff is based on signals and slots).
Upvotes: 1
Reputation: 5225
There's also Signals2 library in Boost, which provides an API very close to real C# events, at least in idiomatic sense.
Upvotes: 1
Reputation: 154005
The basic idea is to take function objects, e.g., something like std::function<Signature>
as the callbacks. These aren't function pointers but can be called. The standard C++ library (for C++ 2011) contains a number of class and functions, e.g., std::mem_fn()
and std::bind()
which allow using functions, including member functions, to be used as function objects.
The part what is missing is something supporting multiple events be registered: std::function<Signature>
represents one function. However, it is easy to put them, e.g., into a std::vector<std::function<Signature>>
. What becomes more interesting (and requires variadic templates to be done easily) is creating an event class which encapsulates the abstraction of multiple events begin registered, potentially unregistered, and called.
Upvotes: 3
Reputation: 10557
C++ has a concept of functor: a callable object. You need to read about them.
Think about an object that has overwritten operator()
. You pass an instance of such an object. After that you can call it like a regular function. And it can maintain a state.
Upvotes: 1