Nidificato classe o no nidificato classe?
-
19-09-2019 - |
Domanda
Ho classe A e A elenco di oggetti. A ha una funzione f che deve essere eseguito ogni X secondi (per la prima istanza ogni 1 secondo, per l'istanza secondi ogni 5 secondi, ecc). Ho una classe di pianificazione che si occupa di eseguire le funzioni al momento giusto. Quello che ho pensato di fare è di creare una nuova classe, atime, che si terrà ptr a un'istanza e il tempo deve essere eseguito un :: f. Lo scheduler terrà una coda min priorità atime.
- Fare si pensa che è la corretta attuazione?
- dovrebbe atime essere una classe annidata dello scheduler?
Soluzione
Da ciò che si descrive, suona come potrebbe funzionare: -)
class IMHO ATime
appartiene allo scheduler oltre ad A. E 'necessario che lo scheduler per fare il suo lavoro, e non è necessaria per A. In realtà, A (e il resto del mondo) non è necessario nemmeno della sua esistenza - in modo da mettere una classe annidata privata del scheduler sarebbe opportuno per me
Altri suggerimenti
Questo può essere un po 'troppo avanzato, ma qui va ...
boost :: funzione e boost :: legano può essere utilizzato per implementare uno scheduler che non ha bisogno di sapere nulla di classe A. Questo renderebbe il programmatore delle più generico e riutilizzabile.
Ecco alcuni esempi di codice che illustra come quelle strutture Boost possono essere utilizzati nel vostro caso:
#include <ctime>
#include <queue>
#include <boost/function.hpp>
#include <boost/bind.hpp>
struct Foo
{
void onScheduler(time_t time) {/*...*/}
};
struct Bar
{
void onScheduler(time_t time) {/*...*/}
};
typedef boost::function<void (time_t)> SchedulerHandler;
struct SchedulerEvent
{
bool operator<(const SchedulerEvent& rhs) const {return when < rhs.when;}
SchedulerHandler handler;
time_t when;
};
class Scheduler
{
public:
void schedule(SchedulerHandler handler, time_t when)
{
SchedulerEvent event = {handler, when};
queue_.push(event);
}
private:
std::priority_queue<SchedulerEvent> queue_;
void onNextEvent()
{
const SchedulerEvent& next = queue_.top();
next.handler(next.when);
queue_.pop();
}
};
int main()
{
Scheduler s;
Foo f1, f2;
Bar b1, b2;
time_t now = time(0);
s.schedule(boost::bind(&Foo::onScheduler, &f1, _1), now + 1);
s.schedule(boost::bind(&Foo::onScheduler, &f2, _1), now + 2);
s.schedule(boost::bind(&Bar::onScheduler, &b1, _1), now + 3);
s.schedule(boost::bind(&Bar::onScheduler, &b2, _1), now + 4);
// Do scheduling...
return 0;
}
Si noti che Scheduler
non sa nulla di Foo
& Bar
, e viceversa. Tutti Scheduler
davvero vuole è un funtore "callback" che corrisponde alla firma specificato da SchedulerHandler
.
Se avete bisogno di un SchedulerEvent
essere cancellabile, le cose si fanno un po 'complicato perché gli oggetti boost::function
non sono comparabili. Per aggirare il problema, è necessario restituire una sorta di gettone "connessione" al momento della registrazione eventi. Questo è essenzialmente ciò che fa Boost.Signal.
Spero che questo aiuti.
Questo tipo di classe è meglio realizzato una struttura privata nidificato all'interno della vostra classe scheduler, in modo da poter accedere facilmente a tutti i campi all'interno della classe scheduler. (Tutti i campi di una struct sono pubblici per impostazione predefinita.)
Per quanto riguarda la seconda parte (e la domanda nel titolo), IMO è completamente una questione di gusto. Si potrebbe altrettanto bene scegliere di ridurre la confusione nella definizione della classe di pianificazione, e mettere in un atime subnamespace con un nome di avviso (come detail
) per impedire alle persone di utilizzarlo. Dopo tutto, se è utile solo per la pianificazione, non c'è molto bisogno di nasconderlo troppo -. Nessuno sta andando a voler utilizzare comunque
Forse potrebbe essere diverso in C ++ 0x (credo di aver sentito alcune voci come sta andando a cambiare le regole di accessibilità fra nidificato e genitore di classe, o giù di lì, nel qual caso la nidificazione potrebbe essere più utile).
Per genericità si potrebbe anche voler fare uso di modelli, e magari finire con Scheduler<A>
(utilizzando un TimedOperation<A>
) (o una miriade di perfezionamenti potenziali / generalizzazioni di questo)?