EDIT: RISOLTOPure metodo virtuale chiamato
Sto lavorando su un progetto multi-threaded in questo momento in cui ho una classe lavoratrice di base, con diversi classi operaie che ereditano da essa. Al runtime, le classi worker diventano thread, che quindi eseguono il lavoro secondo necessità.
ora, ho un direttore che ho scritto che si suppone di mantenere un array di puntatori a tutti i lavoratori, in modo che possa recuperare le informazioni da loro, così come modificare le variabili all'interno di in un secondo momento.
Ho fatto questo con la creazione di un puntatore a un puntatore della classe base:
baseWorkerClass** workerPtrArray;
Poi nel costruttore del direttore, ho allocare dinamicamente un array di puntatori alla classe lavoratrice di base:
workerPtrArray = new baseWorkerClass*[numWorkers];
Nel costruttore di ciascun thread di lavoro, il worker chiama una funzione nel director che è destinata a memorizzare il puntatore di quel worker nella matrice.
Ecco come il regista memorizza i puntatori:
Director::manageWorker(baseWorkerClass* worker)
{
workerPtrArray[worker->getThreadID()] = worker;
}
Ecco un esempio di una variante dei lavoratori. Ogni lavoratore eredita dalla classe worker di base e la classe worker di base contiene pure funzioni virtuali che dovrebbero esistere in tutte le varianti di worker, nonché alcune variabili condivise tra tutti i worker.
class workerVariant : protected baseWorkerClass
{
public:
workerVariant(int id)
: id(id)
{
Director::manageWorker(this);
}
~workerVariant()
{
}
int getThreadID()
{
return id;
}
int getSomeVariable()
{
return someVariable;
}
protected:
int id;
int someVariable
};
Poi il baseWorkerClass sembra qualcosa di simile:
class baseWorkerClass
{
public:
baseWorkerClass()
{
}
~baseWorkerClass()
{
}
virtual int getThreadID() = 0;
virtual int getSomeVariable() = 0;
};
Dopo ogni variante lavoratore è fatto l'inizializzazione, dovrei finire con un array di puntatori a oggetti baseWorkerClass. Ciò significa che dovrebbe essere in grado, ad esempio, ottenere il valore di una data variabile in un certo lavoratore utilizzando il suo ID come indice alla matrice, in questo modo:
workerPtrArray[5]->getSomeVariable(); // Get someVariable from worker thread 5
Il problema è che questo codice provoca un incidente in un eseguibile di Windows, senza alcuna spiegazione del perché, e in Linux, si dice:
metodo virtuale puro chiamato
terminano chiamato senza eccezione attiva
Interrotto
Potrei giurare di averlo fatto funzionare a un certo punto, quindi sono confuso su cosa ho rovinato.
codice non modificato effettivo che ha il problema:
Worker variante intestazione: http://pastebin.com/f4bb055c8
Worker file sorgente variante: http://pastebin.com/f25c9e9e3
Base classe operaia intestazione: http://pastebin.com/f2effac5
Base file di lavoratore sorgente della classe: http://pastebin.com/f3506095b
Intestazione direttore: http://pastebin.com/f6ab1767a
Direttore file sorgente: http://pastebin.com/f5f460aae
EDIT: Informazioni aggiuntive, nella funzione manageWorker, mi può chiamare una delle funzioni virtuali pure dal puntatore "lavoratore", e funziona bene. Al di fuori della funzione manageWorker, quando provo a usare l'array pointer, fallisce.
EDIT: Ora che ci penso, il punto di ingresso del thread è operator(). Il thread Director viene creato prima dei worker, il che può significare che l'operatore parentesi sovraccarico chiama le funzioni pure virtuali prima che possano essere sovrascritte dalle classi child. Sto esaminando questo.
Grazie per l'input. In realtà, riguardo al metodo getThreadID, era solo un'incongruenza da parte mia. Questo non è il codice che sto usando, sono solo cose che ho scritto pochi minuti fa per illustrare in modo chiaro e conciso il mio punto. il metodo getThreadID _is_ pure virtual, e _is_ sovrascritto in ogni variante worker. Tutto il metodo getThreadID restituisce la variabile "id" del thread. – jakogut
Quando un oggetto è in costruzione (mentre il costruttore è eseguito), il meccanismo di funzione virtuale non chiamerà mai in funzioni virtuali di una classe derivata dal tipo dell'oggetto. Questo perché i costruttori di classi derivate devono ancora essere eseguiti.Quindi chiamare un metodo di una classe derivata da un costruttore non funzionerà. Una via d'uscita è la costruzione a due fasi, preferibilmente nascosta dietro un oggetto wrapper. (Lo stesso vale per la distruzione, BTW.) – sbi
Oh, merda, hai ragione, non ci ho pensato. Fammi fare un test rapido qui, e ti riporto. (Passa un'altra ora di sonno.) – jakogut