Nice C++ object oriented code basically means writing everything in objects/classes. However, not everything we need in programming is classes. This article concentrates on callback functions, and presents a C++ implementation of delegates which doesn’t use pointers to functions.
It’s not surprising that callback functions will usually look ugly in C++ code. Pointers to member functions are usually a mess. It is mainly because they need the “this” pointer as a parameter. Observe the following example:
class A {
public:
int func ();
};
...
int (A::*pmf)();
pmf = &A::func;
A a;
A *pa = &a;
(a.*pmf)();
C++ was meant to be nicer than this, wasn’t it?
If you’re familiar with C# programming, one of the new bright ideas in C# is “Delegates”. If you get to the bottom of it, delegates can actually be easily implemented in C++ using regular classes, as shown below.
As a rule of thumb, use the ideas of the following code whenever you want to implement a callback function in C++ and you won’t get disappointed.
Implementing a C++ delegates consist of a few simple tasks. The following example illustrates how to create and use a delegate of a function that takes string and returns void.
1. Declare a prototype of a “pointer to a function that takes string and returns void” as a pure virtual class with one member function:
class StringDelegate
{
public:
virtual void runTheFunction(string params) = 0;
};
2. Implement your specific callback function
The callback function’s implementation is a class that inherits from StringDelegate. Optionally, it would be nicer if it contained some kind of a “Runner” class that is responsible to handle the received data. The code follows:
class OurDelegate : public StringDelegate
{
public:
void runTheFunction(string data); // Implementation!
OurDelegate(Runner& runner); // The constructor should get the runner
private:
OurDelegate(); // No default constructor
Runner m_runner;
};
// The constructor
OurDelegate::OurDelegate(Runner& runner):m_runner(runner)
{
}
// The actual implementation
void OurDelegate::runTheFunction(string data)
{
m_runner.run(data);
}
Now we can write the code that's calling our "callback function":
void callme(StringDelegate sd)
{
sd.runTheFunction("Tralala");
}
Running the delegates is simple:
callme(OurDelegate(runner));
No pointers needed! Now that’s C++.
RSS feed for comments on this post. TrackBack URI
Powered by WordPress