Rein virtuelle Methode VS. Function Pointer
-
20-08-2019 - |
Frage
Vor kurzem habe ich bereits eine Thread-Klasse Bibliothek entwerfen, ich habe einen Thread abstrakte Klasse wie folgt zusammen:
class Thread {
public:
run() { /*start the thread*/ }
kill() { /*stop the thread*/ }
protected:
virtual int doOperation(unsigned int, void *) = 0;
};
Echt Thread Klassen würden diese abstrakte Klasse erben und doOperation
Methode in ihrer eigenen Logik, etwas ähnliches zu implementieren, um Strategie rel="nofollow Muster .
Das Problem ist, dass ich auf einer C-Back-End-Bibliothek verlasse mich die den Faden in der folgenden Funktion definiert ausgeführt wird:
int startThread(char* name, (int)(*)(unsigned int, void*), int, int, int, void*);
Wie Sie sehen können; Der zweite Parameter ist eine Funktion der Schleifenzeiger zum Gewinde (Hauptfunktion), und hier ist das Problem; da ich diese C-Funktion verwenden, um die Gewinde in der run
Verfahren zu starten, gebe ich die Adresse doOperation
auf den zweiten Parameter, und dies nicht getan werden kann, da der Fehlanpassungstyp.
Ich habe versucht, reinterpret_cast
zu verwenden, um einen Zeiger zurück, aber ich ISO-C ++ verbietet einen Zeiger von nicht initialisierten Funktionselement zurück.
Ich weiß nicht, wie man diesen Konflikt zu überwinden, eine statische Methode ist die einzige Lösung, die ich denke, aber es bläst meinen Entwurf Muster auf!
Lösung
Als erstes sollten Sie den Link Michael Burr zur Verfügung gestellt lesen, da es gute Informationen enthält. Dann hier ist C ++ ish Pseudo-Code für sie:
int wrapperDoOperation(int v, void *ctx)
{
Thread *thread = (Thread *)ctx;
return thread->doOperation(v);
}
class Thread {
public:
run() {
startThread("bla", wrapperDoOperation, bla, bla, bla, (void *)this);
}
kill() { /*stop the thread*/ }
protected:
virtual int doOperation(unsigned int) = 0;
friend wrapperDoOperation ......;
};
Die Idee ist, dass doOperation, eine Elementfunktion des Thread ist, braucht keinen void * Kontext, können Sie einfach halten, was Sie als Kontext in dem Objekt selbst passieren würden. Daher können Sie den void-Zeiger verwenden, um den actuall diese Zeiger auf die doOperation passieren. Beachten Sie, dass die void * Details von den Benutzern der Klasse verborgen sind, das ist schön.