Ich habe Callbacks verwendet, um die Kopplung zwischen einigen C++ - Klassen zu reduzieren. Um Begriffe zu definieren: Ich rufe die Klasse an, die die Rückrufe durchführt, und die Klasse, die den Rückruf erhält, den Angerufenen. In der Regel (aber nicht notwendigerweise) besitzt der Angerufene den Anrufer. Der Anrufer hat vom Design her keine Kenntnis vom Angerufenen.Wie kann ich garantieren, dass die Lebensdauer eines Objekts der Dauer einer Mitgliedsfunktion entspricht?
Ich stoße auf ein Problem in Bezug auf die Lebensdauer des Caller-Objekts: Es gibt keine Garantie, dass es nach jedem beliebigen Callback noch am Leben ist. Nehmen Sie dieses einfache Beispiel:
void caller::f()
{
/* Some work */
if (...)
{
/* [1] Execute callback */
_callee->callback(this);
}
/* [2] Some more work */
}
Sagen Sie, dass der Angerufene dynamisch den Anrufer zugewiesen hat, und hat für den Rückruf registriert speziell für einen bestimmten Zustand zu warten, auftreten. Wenn dies der Fall ist, löscht der Angerufene den Anrufer aus dem Rückruf bei [1]. Wenn das der Fall ist, kehrt die Steuerung zu caller :: f zurück, aber this
wurde gelöscht, und jeder Code bei [2] wird höchstwahrscheinlich abstürzen.
Im allgemeinen Fall kann der Aufrufer nichts über den Angerufenen annehmen. Es weiß nicht, ob der Angerufene this
besitzt, oder ob es this
freigeben kann, also würde ich einige allgemeine Mittel benötigen, um die Freigabe für den Bereich der Aufruffunktion des Aufrufers zu verhindern.
Ich glaube eine mögliche Lösung dreht sich um boost::shared_ptrs
und enable_shared_from_this
, obwohl ich es nie benutzt habe. Da diese Callbacks sehr häufig auf mobilen Geräten mit begrenzter Verarbeitungsleistung ausgeführt werden (40+ Mal pro Sekunde), mache ich mir auch Sorgen über den Overhead des Erstellens und Entlassens dieser vielen shared_ptrs
.
Delegierung ist ein ziemlich häufiges Muster in Objective-C. Ich bin weit weniger vertraut mit gängigen C++ - Entwurfsmustern. Gibt es eine schnelle und einfache Lösung für dieses Problem? Wenn nicht, wie würde dieses Design normalerweise in C++ erreicht?
"Angenommen, der Angerufene hat den Anrufer dynamisch zugewiesen ... der Anrufer löscht den Angerufenen aus dem Rückruf ...". Das hört sich gar nicht nach einem guten Design an. – Chad
@Chad: Warum ist das ein schlechtes Design? Wenn der Besitzer die Dienste des Arbeiters nach Erhalt eines Rückrufs nicht mehr benötigt, muss er ihn löschen. –
@Chad: Tut mir leid, ich habe im fraglichen Satz "Caller" und "Callee" getauscht. Ja, die Art, wie ich es geschrieben habe, wäre schrecklich schlechtes Design. Ich hätte Begriffe mit mehr als einem einzelnen Buchstabenunterschied auswählen sollen ... –