Imagine you had a class hierarchy like the following:
class Robot
{
public:
void OnTaskCompleted() {}
private:
Task *m_pTask;
};
class Task
{
public:
virtual void DoTask() = 0;
};
class TidyUp : public Task
{
public:
void DoTask()
{
// When TidyUp task is compeleted invoke OnTaskCompleted() from here.
}
};
I need to call OnTaskCompleted()
from TidyUp::DoTask()
. What would be the recommended way to do that?
I'd like to avoid:
The static
route is not feasible unless there is only one Robot
in your program, and an instance of that robot is available statically.
Passing a Robot
to the task may be OK, but it might reveal too much information and prohibit task usages with objects other than robots.
A third alternative would be to make an interface-like class for completion notifications, extending it in the Robot
, and calling it from the task. Unfortunately, C++ does not make it particularly easy by pushing you into the virtual inheritance territory.
You could adopt a callback approach that is common in POSIX thread libraries (passing a void pointer and a function pointer that takes a void pointer), but that is not too C++-ish.
Finally, if you are using C++11, you have anonymous functions that let you address the issue very gracefully by wrapping both a function and an object on which it operates in a single closure without using an external library, such as boost.
Here is a quick example of the third approach (link to ideone):
#include <iostream>
#include <string>
using namespace std;
class WithNotification {
public:
virtual void notify()=0;
};
class Robot : public virtual WithNotification {
private:
string name;
public:
Robot(const string& n) : name(n) {}
virtual void notify() {cout << name << " has been notified" << endl; }
};
class Task {
private:
WithNotification& onFinished;
public:
Task(WithNotification& f) : onFinished(f) {}
void run() {
cout << "The task is running" << endl;
onFinished.notify();
}
};
int main() {
Robot r1("Quick");
Robot r2("Brown");
Task t1(r1);
Task t2(r2);
t1.run();
t2.run();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With