Lauter Objekte oder STL Container
-
Hallo zusammen,
der Titel ist unglücklich gewählt, aber mir fällt kein besserer ein.
Ich möchte folgendes machen:
Für ein Betriebssystem mit C-API einen Wrapper schreiben, der Systembibliotheken öffnen kann anhand des Namens und der Version.
Das Ganze muss im globalen Namensraum stattfinden.
Ich habe ein gutes Bsp. bei dem die Macher wohl noch nicht auf STL o.ä. zurückgreifen können. Dort wird eine Klasse angelegt, deren Konstruktor Librarynamen und -version bekommt und die nen privaten Member hat, der den Zeiger auf die geöffnete Library entgegennimmt.
Der Destruktor schließt dann die Library wieder.So legt man für jede Lib die man braucht ein solches Objekt außerhalb seiner ganzen Klassen und Methoden an (im MainFile z.B.).
Mein Ansatz wäre nun folgender: Ne statische Klasse mit statischem Vector und ner statichen open-Methode mit Name und Version der Lib. In der Open-Methode wird dann der Zeiger der Lib entgegengenommen und in den Vector gelegt.
Leider verliere ich so die Möglichkeit über nen Destruktor alle geöffneten Libs automatisch schließen zu lassen, so dass man die nicht vergisst!Eine Alternative wäre eine Klasse, deren Objekte bei der Erzeugung den Zeiger der geöffneten Lib entgegennehmen und diese Objekte (bzw. Zeiger darauf) lege ich dann in den statischen Vector. Wenn der Vector out of scope geht werden denn die Destruktoren der Objekte gerufen (oder? auch wenn Zeiger im Vector liegen?), welche die geöffneten Libs schließen.
Was meint ihr?
Oder seh ich da was ganz falsch?
Danke schon mal und
Ciao
-
Hi,
Also entweder versteh ich Dich falsch, oder Du hast n logischen Verdreher drin...
Meinst Du das ?!
class CLibraryLoader { private: HMODULE _hmMod; public: CLibraryLoader(void) : _hmMod(NULL) { } CLibraryLoader(const PTCHAR pszFileName) : _hmMod(LoadLibrary(pszFileName)) { } ~CLibraryLoader(void) { if(_hmMod != NULL) { FreeLibrary(_hmMod); _hmMod) = NULL; } } bool Initialize(const PTCHAR pszFileName) { if(_hmMod != NULL) { FreeLibrary(_hmMod); _hmMod = NULL; } _hmMod = LoadLibrary(pszFileName); return (_hmMod != NULL); } bool Initialize(HMODULE hmExternal) { if(hmExternal == NULL) return (false); if(_hmMod != NULL) { FreeLibrary(_hmMod); _hmMod) = NULL; } _hmMod = hmExternal; return (true); } void Release(void) { if(_hmMod != NULL) { FreeLibrary(_hmMod); _hmMod) = NULL; } } HMODULE GetModule (void) const { return (_hmMod); } bool IsInitialized (void) const { return (_hmMod != NULL); } }Aber ob man dafür ne Klasse braucht...Hm ich weiß nit...

Oder meintest Du was ganz anderes ?! ... Also da würde man dann für jede Library ein Objekt anlegen, was schon sinnvoll ist
.EDIT: Noch was übersehen... :p .
Ist natürlich für Windows
... Aber was das soll
hm kp 
EDIT zur Benutzung:
std::vector<CLibraryLoader> LibArray; // Damit haste auch n STL-Vector dabei.
-
Hi nochmal,
und danke für die Antwort.
Ich meinte sowas ähnliches:
Hier mal das Bsp, welches ich erwähnte ausm Kopp (hab gerad kein Zugriff darauf, also bitte nicht für Tippfehler etc. hauen! Pseudocode!):
class LibraryBaseC { public: LibraryBaseC(string name, in version) : isOpen(false) { base = OpenLibrary(name, version); if (base != NULL) isOpen = true; } ~LibraryBaseC() { if (base != null) CloseLibrary(base); } boolean isOpen() { return isOpen; } private: boolean isOpen; struct Library *base; }Hier wird für jede Library ein eigenes Objekt angelegt. Da die struct Library Zeiger im globalen Namensraum liegen müssen wurden bei diesem Bsp. die Aufrufe:
LibraryBaseC("lib1", 2); LibraryBaseC("lib2", 3); ...In den .cpp-Dateien ausserhalb der Main- und anderen Methoden gemacht und es tat.
Meine Idee ist nun folgende:
class LibraryManagerC { public: static boolean openLibrary(string name, int version) { struct Library *base = OpenLibrary(name, version); if (base != NULL) { libraries.push_back(base); return true; } return false; } static void closeLibraries() { // über Vector iterieren und jeden Eintrag an CloseLibrary() geben } private: static vector<struct Library*> libraries; LibraryManagerC(); ~LibraryManagerC(); // Dazu noch Copykonstruktor und Zuweisungsoperator private machen, damit alles statisch ist! }Hier muss ich aber das closeLibraries() explizit rufen.
Wenn ich nun statt struct Library * Zeiger auf Objekte in den Vector legen würde, würden dann die Destruktoren dieser Objekte mal gerufen werden, da es sich hier doch um ne statische Klasse handelt?!Ciao
-
Du könntest den Manager als Singleton erzeugen und im Destruktor alle vorhandenen Library's aufräumen.
-
Danke, stimmt!
Gibts da Unterschiede (syntaktisch, semantisch) zu Java (da kenne ich mich besser aus)? Weil ich z.B. im Header der Managerklasse ja eine private Variable vom Tyü der Managerklasse angebe?
Aber nochmal zu meiner anderen Frage:
Werden die Destruktoren der Objekte gerufen, deren Zeiger sich in dem statischen Vektor befinden (müssen doch, oder)?
Ciao
-
Reth schrieb:
Danke, stimmt!
Gibts da Unterschiede (syntaktisch, semantisch) zu Java (da kenne ich mich besser aus)? Weil ich z.B. im Header der Managerklasse ja eine private Variable vom Tyü der Managerklasse angebe?
So gut kenne ich mich in Java nicht aus. Auf jeden Fall darfst du in C++ keine rekursiven Datenstrukturen aufbauen (mit Zeigern oder statischen Elementen ist es erlaubt).
Werden die Destruktoren der Objekte gerufen, deren Zeiger sich in dem statischen Vektor befinden (müssen doch, oder)?
Der Vector ruft nur die Destruktoren der enthaltenen Objekte auf (und der "Dtor" eines Zeigers macht nichts weiter) - also "nein".
(du könntest aber auch beide Anläufe kombinieren und einen vector<LibraryBaseC> verwenden)
-
CStoll schrieb:
So gut kenne ich mich in Java nicht aus. Auf jeden Fall darfst du in C++ keine rekursiven Datenstrukturen aufbauen (mit Zeigern oder statischen Elementen ist es erlaubt).
Wie macht man dann in C++ ein Singleton? Hab nur gelesen, dass es mit Hilfe statischer Variablen möglich ist ne rekursive Struktur einer Klasse, die eine Variable von ihrem Typ enthält aufzubauen (in Thinking in C++).
Der Vector ruft nur die Destruktoren der enthaltenen Objekte auf (und der "Dtor" eines Zeigers macht nichts weiter) - also "nein".
(du könntest aber auch beide Anläufe kombinieren und einen vector<LibraryBaseC> verwenden)Das wollte ich eigentlich nicht, da ich nicht möchte, dass von allen Objekten Kopien im Vektor liegen.
Ciao
-
Reth schrieb:
CStoll schrieb:
So gut kenne ich mich in Java nicht aus. Auf jeden Fall darfst du in C++ keine rekursiven Datenstrukturen aufbauen (mit Zeigern oder statischen Elementen ist es erlaubt).
Wie macht man dann in C++ ein Singleton? Hab nur gelesen, dass es mit Hilfe statischer Variablen möglich ist ne rekursive Struktur einer Klasse, die eine Variable von ihrem Typ enthält aufzubauen (in Thinking in C++).
Google hilft sicher
Ein grober Entwurf könnte z.B. so aussehen:class Singleton { static Singleton the_object; //Copy-Ctor und op= entschärft Singleton(const Singleton&); Singleton operator=(const Singleton&); public: static Singleton& getInstance() { return the_object; } };(je nach Bedarf lässt sich der Ansatz noch anpassen - schau dich mal um)
Der Vector ruft nur die Destruktoren der enthaltenen Objekte auf (und der "Dtor" eines Zeigers macht nichts weiter) - also "nein".
(du könntest aber auch beide Anläufe kombinieren und einen vector<LibraryBaseC> verwenden)Das wollte ich eigentlich nicht, da ich nicht möchte, dass von allen Objekten Kopien im Vektor liegen.
OK, das ist ein Argument. Da würden mir noch zwei Lösungen einfallen:
a) Du räumst den vector von Hand aus, bevor er endgültig gelöscht wird (im DTor der Manager-Klasse)
b) In der Boost Bibliothek gibt es afaik Pointer-Versionen der STL-Container, die beim Löschen ihre Elemente delete'n
-
Danke!
CStoll schrieb:
Google hilft sicher

Ich weiss, ich weiss (schäm).
Ein grober Entwurf könnte z.B. so aussehen:
class Singleton { static Singleton the_object; //Copy-Ctor und op= entschärft Singleton(const Singleton&); Singleton operator=(const Singleton&); public: static Singleton& getInstance() { return the_object; } };(je nach Bedarf lässt sich der Ansatz noch anpassen - schau dich mal um)
Muss man den Defaultkonstruktor nicht mit angeben? Ist der dann automatisch private?
OK, das ist ein Argument. Da würden mir noch zwei Lösungen einfallen:
a) Du räumst den vector von Hand aus, bevor er endgültig gelöscht wird (im DTor der Manager-Klasse)
b) In der Boost Bibliothek gibt es afaik Pointer-Versionen der STL-Container, die beim Löschen ihre Elemente delete'nWie sähe dass denn bei meinem Bsp. aus? Wenn die Klasse nur statische Methoden enthält und der Vector auch statisch ist, wird ja kein Konstruktor benötigt und somit auch kein Destruktor gerufen, oder?
Bei rein statischen Klassen wird der private Destruktor doch nie gerufen, oder ist das in C++ anders?
Blieben dann der Singleton-Ansatz oder ein Blick in die boost-Geschichten.Ciao
-
CodeFinder schrieb:
class CLibraryLoader { private: HMODULE _hmMod; // und jede Menge weiteren Code, aber kein Copykonstruktor oder AssignmentoperatorAber ob man dafür ne Klasse braucht...Hm ich weiß nit...

std::vector<CLibraryLoader> LibArray; // Damit haste auch n STL-Vector dabei.Das Beispiel hat leider einen Fehler. Der Klasse fehlt ein Kopierkonstruktor und ein Zuweisungsoperator. Diese sind notwendig, da Du im Destruktor eine wesentliche Aufräumarbeit vornimmst.
Stell Dir vor, Du hast eine Instanz der Klasse und legst eine Kopie davon an. Dies passiert beispielsweise, wenn Du sie in den vector steckst oder kann sogar schon passieren, wenn Du den vector veränderst. Dann wird die Bibliothek nur ein mal geladen, aber mehrfach entladen.
{ CLibraryLoader lib1("meineLib.dll"); // hier wird geladen LibArray l; l.push_back(lib1); // hier wird eine Kopie angelegt } // hier wird sowohl lib1 als auch das Objekt aus dem vector gelöscht, // also 2 mal frei gegeben.Die Lösung wäre, einen Zeiger auf einen Referenzzähler mitzuführen, die die Anzahl der Instanzen zählt. Dies geht am einfachsten über einen Smart-Pointer.
Tntnet
-
@tntnet:
Schlaues Kerlchen! Das war auch NUR demonstrativ! Das sollte KEINE ausgefeilte Klasse sein, natürlich fehlt da noch einiges... :xmas2: