What is the recommended way to call the callback function defined in the container class from the contained class?

Imagine you had a class hierarchy, for example:

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()out TidyUp::DoTask(). What would be the recommended way to do this?

I would like to avoid:

  • creating OnTaskCompleted () static
  • transfer of the robot pointer to the task
+5
source share
4 answers

A route is staticimpossible if your program does not have only one Robot, and an instance of this robot is available statically.

The transfer of the Robottask may be in order, but it may display too much information and prohibit the use of the task using objects other than robots.

, , , Robot . , ++ , .

, POSIX ( void , void), ++ - ish.

, ++ 11, , , , , boost.

( 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();
}
+3

. Task Robot, TaskDelegate :

class TaskDelegate
{
public:
    virtual void onTaskFinished(Task *sender) = 0; //implement in successors

protected:
    ~TaskDelegate() {} //don't allow deletion via interface pointer
};

Task :

class Task
{
    Task(TaskDelegate *delegate) {...}
    ...
};

Robot delegate

class Robot : public TaskDelegate {...}

, Task , TaskDelegate

0

, . - Robot , OnTaskCompleted, Task Robot Task. , Robot , Task .

Task this->OnTaskCompleted . - :

template<class Callback>
class Task
{
public:
    void DoTask()
    {
        // ...

        Callback();
    }
};

class Robot
{
public:
    Robot()
    {
        m_pTask = new Task<this->OnTaskCompleted>;
    }

    // ...
};

, , .

, , , . "" "" . , Task.

0

Xeo, - :

#include <iostream>
#include <functional>

typedef std::tr1::function<void (int)> CallbackFunc;

class Task
{
public:
    Task(CallbackFunc callbackFunc) : m_callbackFunc(callbackFunc) {}
    virtual ~Task() {}
    virtual void DoTask() = 0;
protected:
    CallbackFunc m_callbackFunc; 
};

class TidyUp : public Task
{
public:
    TidyUp(CallbackFunc callbackFunc) : Task(callbackFunc) {}
    void DoTask() {
        std::cout << "I love tidying up!" << std::endl;
        m_callbackFunc(6); // When TidyUp task is compeleted invoke OnTaskCompleted() from here.
    }
};

class Robot : private Uncopyable
{
public:
    Robot() : m_pTask(new TidyUp(std::bind(&Robot::OnTaskCompleted, this, std::placeholders::_1))) {}
    ~Robot() { delete m_pTask; }
    void DoTask() { m_pTask->DoTask(); }
    void OnTaskCompleted(int nCleannessLevel) { std::cout << "Done!  Cleanness Level: " << nCleannessLevel << std::endl; }
private:
    Task *m_pTask;
};

int main()
{
    Robot robot;
    robot.DoTask();
    return 0;
}
0

All Articles