La route static
non è fattibile a meno che non ci sia un solo Robot
nel programma e un'istanza di quel robot sia disponibile staticamente.
Il passaggio a Robot
dell'attività può essere corretto, ma potrebbe rivelare troppe informazioni e vietare l'utilizzo di attività con oggetti diversi dai robot.
Una terza alternativa sarebbe quella di creare una classe simile all'interfaccia per le notifiche di completamento, estendendola nello Robot
e richiamandola dall'attività.Sfortunatamente, il C++ non lo rende particolarmente facile spingendoti nel territorio dell'ereditarietà virtuale.
È possibile adottare un approccio di richiamo che è comune nelle librerie di thread POSIX (passando un puntatore del vuoto e un puntatore di funzione che accetta un puntatore del vuoto), ma che non è troppo C++ - ish.
Infine, se si utilizza C++ 11, si ha anonymous functions che consente di risolvere il problema in modo molto elegante avvolgendo sia una funzione che un oggetto su cui opera in una singola chiusura senza utilizzare una libreria esterna, ad esempio Incremento.
Ecco un rapido esempio del terzo approccio (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();
}
Chi sta chiamando 'DoTask'? –
È possibile comprimerlo in una funzione 'std ::' passando 'std :: bind (& Robot :: OnTaskCompleted, this)'. –
Xeo
@ AndreasBrinck-Ho ora modificato il mio codice. – jpen