Ich weiß, dass dies so oft gefragt wurde, und aus diesem Grund ist es schwierig, durch die Kruft zu graben und ein einfaches Beispiel dafür zu finden, was funktioniert.
Ich habe das, es ist einfach und es funktioniert für MyClass
...
#include <iostream>
using std::cout;
using std::endl;
class MyClass
{
public:
MyClass();
static void Callback(MyClass* instance, int x);
private:
int private_x;
};
class EventHandler
{
public:
void addHandler(MyClass* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
EventHandler* handler;
MyClass::MyClass()
{
private_x = 5;
handler->addHandler(this);
}
void MyClass::Callback(MyClass* instance, int x)
{
cout << x + instance->private_x << endl;
}
int main(int argc, char** argv)
{
handler = new EventHandler();
MyClass* myClass = new MyClass();
}
class YourClass
{
public:
YourClass();
static void Callback(YourClass* instance, int x);
};
Wie kann das umgeschrieben werden, so EventHandler::addHandler()
wird mit beiden MyClass
und funktionieren YourClass
. Es tut mir leid, aber es ist nur die Art und Weise, wie mein Gehirn funktioniert. Ich muss ein einfaches Beispiel dafür sehen, was funktioniert, bevor ich verstehen kann, warum / wie es funktioniert. Wenn Sie jetzt eine bevorzugte Methode haben, um diese Funktion zum Vorführen zu bringen, markieren Sie diesen Code und senden Sie ihn zurück.
[bearbeiten]
Es wurde beantwortet, aber die Antwort wurde gelöscht, bevor ich das Häkchen setzen konnte. Die Antwort in meinem Fall war eine Vorlagenfunktion. AddHandler zu diesem geändert ...
class EventHandler
{
public:
template<typename T>
void addHandler(T* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
Antworten:
Anstatt statische Methoden zu haben und einen Zeiger auf die Klasseninstanz zu übergeben, können Sie die Funktionalität des neuen C ++ 11-Standards verwenden:
std::function
undstd::bind
:Die
addHandler
Methode akzeptiert jetzt einstd::function
Argument, und dieses "Funktionsobjekt" hat keinen Rückgabewert und verwendet eine Ganzzahl als Argument.Um es an eine bestimmte Funktion zu binden, verwenden Sie
std::bind
:Sie müssen
std::bind
beim Hinzufügen des Handlers verwenden, da Sie den ansonsten implizitenthis
Zeiger explizit als Argument angeben müssen . Wenn Sie eine freistehende Funktion haben, müssen Sie nicht verwendenstd::bind
:Wenn der Ereignishandler
std::function
Objekte verwendet, können auch die neuen C ++ 11- Lambda-Funktionen verwendet werden :quelle
std::bind
nur ein (nicht angegebenes) Objekt zurückgegeben. Wenn Sie damit fertig sind, können Sie es einfach aus dem Gültigkeitsbereich entfernen . Wenn das gebundene Objekt zerstört wird und Sie versuchen, die Funktion aufzurufen, erhalten Sie ein undefiniertes Verhalten .handler->addHandler()
bedeutet, dass Sie irgendwo ein Objekt erstellen vonEventHandler
? Gute Antwort übrigens +1....., _1, _2)
und so weiter.Hier ist eine übersichtliche Version, die mit Rückrufen von Klassenmethoden und mit Rückrufen von regulären Funktionen funktioniert. In diesem Beispiel verwendet die Rückruffunktion zwei Parameter, um zu zeigen, wie Parameter behandelt werden:
bool
undint
.Dies beschränkt den C ++ 11-spezifischen Code auf die addCallback-Methode und private Daten in der Klasse Caller. Zumindest für mich minimiert dies die Wahrscheinlichkeit von Fehlern bei der Implementierung.
quelle
Sie möchten eine Schnittstelle erstellen, die diesen Code verarbeitet, und alle Ihre Klassen implementieren die Schnittstelle.
Beachten Sie, dass die Funktion "Rückruf" nicht statisch ist, was meiner Meinung nach eine Verbesserung darstellt. Wenn Sie möchten, dass es statisch ist, müssen Sie dies tun, wie JaredC es mit Vorlagen vorschlägt.
quelle
Ein vollständiges Arbeitsbeispiel aus dem obigen Code .... für C ++ 11:
Die Ausgabe sollte sein:
quelle
MyClass
undYourClass
beide könnten abgeleitet werden, vonSomeonesClass
denen eine abstrakte (virtuelle)Callback
Methode hat. IhraddHandler
würde Objekte vom Typ akzeptierenSomeonesClass
undMyClass
undYourClass
außer Kraft setzen könnenCallback
ihre spezifische Implementierung von Callback - Verhalten zu schaffen.quelle
Wenn Sie Rückrufe mit unterschiedlichen Parametern haben, können Sie Vorlagen wie folgt verwenden:
// Kompilieren mit: g ++ -std = c ++ 11 myTemplatedCPPcallbacks.cpp -o myTemplatedCPPcallbacksApp
quelle
YourClass
. Sie scheinen diese Klasse entfernt und eine andere hinzugefügt zu habenOtherClass
. Darüber hinaus hat die Frage bereits eine gut aufgenommene Antwort. Inwieweit ist Ihre Lösung besser, sodass es sich lohnt, sie zu veröffentlichen?