Ich habe diesen vorhandenen Code, in dem sie eine Klasse und eine Initialisierungsmethode in dieser Klasse haben. Es wird erwartet, dass das Objekt der Klasse nach seiner Erstellung initialize aufgerufen werden muss.
Grund für die Existenz der Initialisierungsmethode Das Objekt wird frühzeitig mit einem globalen Gültigkeitsbereich erstellt und die Initialisierungsmethode wird später aufgerufen, nachdem eine DLL geladen wurde, von der es abhängt.
Problem mit der Initialisierung Die Klasse hat jetzt den Bool isInitialized, der in jeder Methode überprüft werden muss, bevor er fortfährt, und einen Fehler zurückgibt, wenn er nicht initialisiert ist. Einfach ausgedrückt, es ist ein großer Schmerz.
Eine mögliche Lösung Initialisieren Sie im Konstruktor. Haben Sie nur einen Zeiger auf das Objekt im globalen Bereich. Erstellen Sie das eigentliche Objekt, nachdem die DLL geladen wurde.
Problem mit der obigen Lösung Jeder, der ein Objekt dieser Klasse erstellt, muss wissen, dass es erst erstellt werden muss, nachdem die DLL geladen wurde, da es sonst fehlschlägt.
Ist das akzeptabel?
call_once
C ++ 11 . Projekte, die sich noch nicht in C ++ 11 befinden, sollten untersuchen, wie call_once in C ++ 11 implementiert wird (konzentrieren Sie sich darauf, welches Problem es löst, und dann wie), und es dann in ihrer (veralteten) Version von C ++ erneut implementieren. Es benötigt ein Multithread-sicheres Synchronisationsprimitiv, dessen Status statisch initialisiert werden muss (mit einem konstanten Wert). Beachten Sie, dass Compiler vor C ++ 11 möglicherweise andere Besonderheiten aufweisen, die erfüllt werden müssen.Antworten:
Klingt nach einer Arbeit für einen virtuellen Proxy.
Sie können einen virtuellen Proxy erstellen, der einen Verweis auf das betreffende Objekt enthält. Solange die DLL nicht geladen ist, kann der Proxy Clients ein bestimmtes Standardverhalten bieten. Sobald die DLL geladen ist, leitet der Proxy alle Anforderungen einfach an den realen Betreff weiter.
Der virtuelle Proxy ist für die Überprüfung der DLL-Initialisierung verantwortlich und entscheidet auf dieser Grundlage, ob die Anforderung an den realen Betreff delegiert werden soll.
Proxy-Muster in Wikipedia
Wie findest du diese Idee?
quelle
Es tritt nichts Nützliches auf, wenn die DLL noch nicht geladen ist. Das Objekt erzeugt nur einen Fehler. Ist es ein schwerwiegender Fehler? Wie wird der Fehler behandelt?
Stellt Ihre Testmethode sicher, dass dieser Fehler im fertigen Produkt niemals auftritt?
Es klingt wie ein Job zum Testen, nicht für architektonisches Design. Gib nicht einfach einen Fehler zurück,
assert
der niemals passiert.Korrigieren Sie alle Clients der Klasse, die den Fehler derzeit abfangen und ignorieren, und versuchen Sie nicht, ihn an erster Stelle auszulösen.
Ein Multithread-Muster kann darin bestehen, nach dem Laden der DLL eine gemeinsam genutzte Bedingungsvariable festzulegen und den Konstruktor des Objekts warten zu lassen (und andere Threads zu blockieren), bis die DLL geladen ist.
quelle
Das erste: Vermeiden Sie globale Objekte als Schädling, es sei denn, ihr Zustand ändert sich nie (Konfiguration).
Nun, wenn Sie aus irgendeinem Grund nicht weiterkommen, gibt es verschiedene Designs, die Ihnen wahrscheinlich helfen könnten.
Ich hatte zwei Ideen:
Verwenden Sie eine Fassade, um die DLL zu laden. Auf das Objekt kann nur über die Fassade zugegriffen werden. Die Fassade lädt die DLL bei der Erstellung und instanziiert das Objekt gleichzeitig.
Verwenden Sie einen Proxy, aber die kluge Art;)
Lassen Sie mich auf den zweiten Punkt näher eingehen , da ich befürchte, die Antwort von @edalorzo könnte Sie erschrecken:
Jetzt haben Sie nur noch einen Scheck.
Dies kann auch durch eine Art Smart Pointer erfolgen:
Hier reservieren Sie nur Platz für einen Zeiger, anfangs null, und erst wenn die DLL geladen ist, ordnen Sie das Objekt tatsächlich zu. Alle vorherigen Zugriffe sollten eine Ausnahme auslösen (NullException: p?) Oder das Programm (sauber) beenden.
quelle
Das ist eine knifflige Frage. Ich habe das Gefühl, dass Architektur bei dem Problem helfen kann.
Aus dem Beweis, es klingt wie die DLL nicht geladen wird, wenn das Programm geladen wird. Es klingt fast wie ein Plugin.
Eine Sache, die in den Sinn kommt, ist, dass Sie die DLL initialisieren müssen. Der Programmierer muss davon ausgehen, dass das Objekt sowieso nicht zuverlässig zurückkommt. Möglicherweise können Sie dies ausnutzen (
bool isObjectLoaded() { return isInitialized; }
), aber Sie erhalten definitiv mehr Fehlerberichte über Ihre Überprüfungen.Ich dachte an einen Singleton.
Wenn Sie den Singleton aufrufen, sollte er das richtige Objekt zurückgeben, wenn er eines abrufen kann. Wenn es nicht das richtige Objekt zurückgeben kann, sollten Sie einen Fehlerwert / nullptr / empty base object erhalten. Dies würde jedoch nicht funktionieren, wenn das Objekt an Ihnen sterben könnte.
Wenn Sie mehrere Instanzen des Objekts benötigen, können Sie stattdessen eine Factory verwenden.
quelle