Unbekannte Klasse zur Laufzeit laden.
-
Wie kann man in C++ eine klasse deren Namen man zur Compilezeit noch nicht kennt später laden? Die Klasse implementiert dann ein Interface und der Name wird später in einer Konfigurationsdatei angegeben.
-
Also das geht nur, wenn die Klasse natürlich trotzdem kompiliert und verlinkt wurde. Dann kannst du anhand eines Strings (wo der herkommt ist egal) eine Klasse instanzieren. Das geht allerdings nicht mit C++-Sprachmitteln, dazu mußt du dir eine generische Faktory entwickeln. In der LOKI Library gibts sowas bzw. im Buch "Modernes C++ Design" wird dies genauer erklärt.
-
Gibts nichts ähnliches wie in Java?
Class clazz = Class.forName("java.util.Date"); Object o = clazz.newInstance();
-
Hallo
nein soetwas gibt es im C++ Standard nicht, weil in C++ die Typen nur zur Compiletime zur Verfügung stehen. Zwar gibt es RTTI, aber das ist nur zur Überprüfung, nicht zum Erstellen von Instanzen.
Du must dir soetwas selber über das bereits genannte Factory-Pattern schreiben.
Oder du benutzt externe Codes die ebenfalls schon genannt wurden.bis bald
akari
-
akari schrieb:
nein soetwas gibt es im C++ Standard nicht, weil in C++ die Typen nur zur Compiletime zur Verfügung stehen. Zwar gibt es RTTI, aber das ist nur zur Überprüfung, nicht zum Erstellen von Instanzen.
Du must dir soetwas selber über das bereits genannte Factory-Pattern schreiben.
Hä
Wie soll ich mir das selber schreiben wenns nicht geht? Wie soll den dann das Factory-Pattern helfen?
-
Gast2 schrieb:
akari schrieb:
nein soetwas gibt es im C++ Standard nicht, weil in C++ die Typen nur zur Compiletime zur Verfügung stehen. Zwar gibt es RTTI, aber das ist nur zur Überprüfung, nicht zum Erstellen von Instanzen.
Du must dir soetwas selber über das bereits genannte Factory-Pattern schreiben.
Hä
Wie soll ich mir das selber schreiben wenns nicht geht? Wie soll den dann das Factory-Pattern helfen?So was gibt es im Standard C++ nicht, es lässt sich aber nachbauen meinte er.
mfg.
-
Irgendwie geht alles, wenn man will. Nur verfolgt halt C++ ein anderes Konzept als Java. Du kannst aber (und wie oft sollen wir das ihn diesem Thread noch sagen?) nachbauen. Dabei mußt du dir das nicht mal aus den Fingern saugen, sondern kannst dich auf die Arbeit anderer stützen... welche, habe ich oben schon genannt.
-
Könnte mit Loki in etwa so aussehen:
#include <iostream> #include <loki/Factory.h> #include <loki/SmartPtr.h> struct Base { virtual void Foo() = 0; // Rein virtuelle Funktion }; struct ClassA : public Base { // Alle klassen müssen von Base ableiten void Foo() { std::cout << "Fuer die Baeume!"; } }; struct ClassB : public Base { void Foo() { std::cout << "Der Mond ist hell heute nach!"; } }; template<class T> T* CreateUsingNew() { // Kann für einzelne Klassen spezialisiert werden return new T; } typedef Loki::Factory<Base, std::string> MyFactory; // Zweite Parameter gibt die Unterscheidung an, kann auch int sein. int main() { MyFactory m; m.Register("A", CreateUsingNew<ClassA>); // Du kannst den Klassen auch andere Namen m.Register("B", CreateUsingNew<ClassB>); // als im Sourcecode geben. std::cout << "Welche Klasse moechtest du erstellen? [A/B]" << std::endl; std::string classname; std::cin >> classname; try { Loki::SmartPtr<Base> p = m.CreateObject(classname); p->Foo(); } catch(std::exception& e) { std::cout << "Exception: " << e.what() << std::endl; } }Ich meine so eine CreateUsingNew-Funktion gibt's schon in der Loki-Lib, oder? Hab das jetzt nicht gefunden.
mfg.
edit: Vergessen den Pointer wieder zu deleten, hab jetzt n SmartPtr genommen.
-
Ein Beispiel zu dem Factory-Pattern. Ich glaube der Code ist selbsterklärend...
#ifndef __GUI_H__ #define __GUI_H__ #include <iostream> class IButton { public: virtual void describe() const = 0; }; class PushButton : public IButton { public: virtual void describe() const { std::cout << "call PushButton::describe\n" << std::flush; } }; class ToggleButton : public IButton { public: virtual void describe() const { std::cout << "call ToggleButton::describe\n" << std::flush; } }; class ToolButton : public IButton { public: virtual void describe() const { std::cout << "call ToolButton::describe\n" << std::flush; } }; #endif // __GUI_H__#ifndef __GUIFACTORY_H__ #define __GUIFACTORY_H__ #include "gui.h" #include <string> class GUIFactory { public: static IButton* create(std::string x) { if (x == "push") return new PushButton; if (x == "toggle") return new ToggleButton; if (x == "tool") return new ToolButton; return 0; } static void usage() { std::cout << "{push|toggle|tool}\n" << std::flush; } }; #endif // __GUIFACTORY_H__#include <iostream> #include <iterator> using namespace std; #include "gui.h" #include "guifactory.h" int main() { GUIFactory::usage(); string tmp = ""; while (cin >> tmp) { IButton *b = GUIFactory::create(tmp); if (b) { b->describe(); delete b; } } }
-
Das Factory Pattern kenne ich, aber das löst nicht das Problem. Da muss ich doch wieder die Klassen zur Compilezeit kennen.
-
Hallo
wie bereits gesagt geht es in C++ nicht anders, alle Typen müßen immer zur Compile-Time bekannt sein.
bis bald
akari
-
Gast2 schrieb:
Das Factory Pattern kenne ich, aber das löst nicht das Problem. Da muss ich doch wieder die Klassen zur Compilezeit kennen.
Ja. Welche Klasse aber erstellt wird, das wird zur Laufzeit entschieden.
mfg.
-
Also die generische Factory aus der LOKI bzw. dem Buch "Modernes C++ Design" erfüllt eigentlich schon diesen Wunsch. Denn jede neue Klasse meldet sich einfach bei der Factory an, so das die Factory diese kennt. Und der Benutzer der Factory kann dann einfach durch einen String eine Klasse instanzieren lassen.
Am Ende wird man aber trotzdem nicht drum herum kommen, jede Klasse dazu zu kompilieren und linken. Das muss halt bei C++ so sein. Aber mit dieser Factory kann man trotzdem ein paar nette Dinge anstellen, die man sonst in C++ von Haus aus nicht machen kann.
Kauft euch einfach das Buch, und werdet schlauer.

-
Die Lösung des Problems heißt dlopen und dlsym. Suche einfach mal hier in den Foren. Da gabe es in letzter Zeit mehrere Diskussionen.
Es ist ja eigentlich sowas wie ein Plugin. Das heißt ein Programmteil, welches zur compilezeit nicht bekannt ist.
Tntnet