Zu Beginn initialisieren
-
Hallo!
Ich möchte zu Programmstart bereits einige Funktionspointer in einer Map haben.
Zu diesem Zweck habe ich mir bei Alexandrescu (Modern C++ Design, 8.3
Implementing an Object Factory) folgende Technik abgeschaut:bool foo(..,..) { myMap.insert(..,..); return true; } File.cpp namespace { const bool nichts = foo(..,..); }Das funktioniert auch bestens, wenn der Code als gewöhnliche Anwendung
compiliert wird.Gerade habe ich die Anwendung aber als statische Library gebaut (GCC), und
eine Anwendung, die diese Library verwendet, findet eine leere Map vor.
Warum versagt diese Technik bei Libraries?Danke,
-
-
Kurzfassung:
Das Programm mit dem du getestet hast, referenziert vermutlich keine Funktion aus "File.cpp". Daher verwirft der Linker das ganze "Objekt" ("File.obj"), und die Initialisierung wird nicht ausgeführt.
-
Nexus schrieb:
Danke für den Link. So wie es aussieht, kann ich das automatische Registrieren
bei der Factory dann vergessen. Die Tricks, damit das doch läuft, sehen auf-
wändiger aus, als irgendwo ein #include-Monster zu bauen, das alle Klassen
kennt.
-
Wieso aufwendiger? Du mußt nur dafür sorgen, daß die map vor der ersten Verwendung gefüllt wird - und mit einer lokalen statischen Variable ist das gesichert (im Gegensatz zu globalen Variablen):
map<..>& getMap() { static map<..> theMap; if(theMap.empty()) { //hier alle notwendigen Werte eintragen } return theMap; }-> Jeder, der die Map verwenden will, muß über diese Funktion zugreifen und erhält ein verwertbares Ergebnis.
-
CStoll schrieb:
Wieso aufwendiger? Du mußt nur dafür sorgen, daß die map vor der ersten Verwendung gefüllt wird - und mit einer lokalen statischen Variable ist das gesichert (im Gegensatz zu globalen Variablen):
map<..>& getMap() { static map<..> theMap; if(theMap.empty()) { //hier alle notwendigen Werte eintragen } return theMap; }-> Jeder, der die Map verwenden will, muß über diese Funktion zugreifen und erhält ein verwertbares Ergebnis.
Ich habe vorhin nur eine Kurzversion formuliert. Das Ziel ist eine Factory, die
keine Header der zu erzeugenden Klassen einbindet. Das heißt, die Factory weiß
nicht, was sie erzeugt. Stattdessen registriert sich jede zu erzeugende Klasse
beim Programmstart mit einem Paar aus ID und Funktionspointer bei der Factory.Eine zu erzeugende Klasse MyClass registriert sich z.B. von ihrem *.cpp-File
aus mit dem Macro:ALG_REGISTRATION(MYCLASS_ID,MyClass)...das so aussieht:
#define ALG_REGISTRATION( atype , algClass ) \ namespace { \ AlgorithmBasePtr getAlgorithm(..) \ { \ return AlgorithmBasePtr(new algClass(..));\ } \ const bool registered=AFactory::getInstance()->registerAlgorithm((atype),getAlgorithm); \ }Dabei ist die Zeile "const bool registered=..." interessant. Sie registriert
bei der Factory die ID und den zugehörigen Funktionspointer auf getAlgorithm(),
so daß die Factory später nur mit der ID das ihr unbekannte Objekt erzeugen
kann.Genial, und aus einem Buch von Alexandrescu. Bloß wird eben diese eine Zeile,
die das Registrieren vornimmt, bei der statisch gelinkten Library nicht mehr
ausgeührt.
-
Pack alle
ALG_REGISTRATION()Aufrufe in ein "zentrales" Header File deiner LIB.
Ich hab' immer ein "Common.h" File das dann alle anderen Header-Files einer LIB/EXE als erstes inkludieren. Das wäre ein guter Platz.