UserControl *control = new GetDerivedControlClass();
-
Hallo Leute, ich suche eine Lösung für folgendes Problem.
Und zwar lese ich eine Xml-Datei ein. Diese enthält zum Beispiel einen Knoten
<DerivedControl>...</DerivedControl>. Und auf der Code-Seite gibt es jetzt noch eine dazugehörige Klasse
class DerivedControl: public UserControl {};Das Problem ist, dass ich als Programmierer weder von der Klasse noch vom Inhalt der Xml-Datei etwas weis.
Wenn ich also den Knoten "DerivedControl" (der Name ist natürlich beliebig) ermittelt habe möchte ich nun ein Object davon erzeugen. Ich kenne allerdings die Basisklasse "UserControl". Gedacht habe ich mir in etwa folgendes://Pseudocode: UserControl *control = new GetDerivedControlClass(); oder UserControl *control = new FindClassInNamespace(namespace); oder UserControl *control = new typeid(GetDerivedControlClass());Ich hoffe es wird klar was ich machen möchte? Ist das irgendwie möglich?
Gruß
Mountainking
-
Das Problem ist dass ich als Programmierer ... von der Klasse [nichts] weis.
Was meinst du damit? Von Objekten die der Compiler nicht kennt, kannst du auch keine Instanzen erstellen. Dem Compiler muss die Klasse vollständig bekannt sein, zumindest die Klassendeklaration. Wenn die Implementierung fehlt gibt es aber Linkerfehler. Die bei dir wahrscheinlich erst zur Laufzeit auftreten. Weiß ich aber nicht.
Wegen RTTI würde ich mich noch mal genauer schlau machen, ob bei allen Compilern auch die selben Namen raus kommen. Sonst bekommst du Probleme mit deinem Namen im XML-File.
Solche lustigen Sachen kann man mit Java übrigens viel einfacher machen. Google mal nach Java Reflection, vielleicht hat sich auch schon jemand Gedanken gemacht Reflections in C++ umzusetzen. Sonst schreit deine Idee noch nach einer Factory.
Nur damit du mal ein paar Buzzwords hast, mit denen du Google füttern kannst.
-
Es ist so dass ich eine Library (dll) zur Verfügung stelle. Die Benutzer sollen dann natürlich auch eigene Steuerelemente (von UserControl abgeleitet) erstellen können. D.h. wenn der Benutzer seine Anwendung mit meiner dll kompiliert muss ich ja irgendwie auf dessen "DerivedControl" Klasse zugreifen können, um Objekte von dieser instanzieren zu können. Dafür brauche ich dann eine Funktion (der man evtl. noch den namespace in dem sie suchen soll noch übergibt) die mir den Klassentyp zurück gibt. Wenn man so will einen Zeiger auf die Klasse.
Dann stellt sich allerdings immer noch die Frage ob das hierUserControl *control = new GetClass();überhaupt so einfach funktioniert. Mit Java geht es wohl, aber mit C++? Ich werde morgen mal schauen, ob ich mit deinen Stichworten weiterkomme.
-
Wenn es dir gar nicht so sehr um so eine Factory-Klasse geht, dann ist es auch in C++ kein Problem. Deine DLL muss ja gar nicht die Klassen kennen, wenn es nur auf die Basis-Methoden agieren soll. Dazu muss aber der Benutzer deiner DLL nicht nur die Klasse selber schreiben, sondern auch erstellen. Was du aber beachten solltest ist, dass sich solche Konstrukte, soweit ich informiert bin, nicht zur Laufzeit linken lassen. Zumindest nicht so, dass du einfach Klassen auf herkömmlichen Weg benutzen kannst. Es ist aber möglich dafür ein C-Interface bereit zu stellen und den "Methoden" jeweils den this-Zeiger mit bei zugeben.
-
Ich würde z.B. eine abstrakte Fabrik bereitstellen, bei der sich die Klassen aus einer DLL beim Laden registrieren.
bool Factory::Register(Key, Creator);Die Klasse DerivedControl registriert sich dann
static bool dummy = Factory::Instance().Register("DerivedControl", CreateDerivedControl)Die Anwendung kann dann ohne die konkreten Klassen zu kennen, mit dem Schlüsselwort "DerivedControl" von der Factory eine Instanz anfordern.
USerControl* control = Factory::Instance().Create("DerivedControl");
-
Ok, ich bin jetzt so weit, dass ich die Factory implementieren kann.
Was ich mich jetzt noch frage ist, wie ich die einzelnen Klassen nun registrieren lasse. Irgendwo muss ich ja den Aufruffactory.Register<BeispielKlasse>("BeispielKlasse");unterbringen. Ideal wäre es wenn sich die Klassen selber registrieren würden. Ich könnte den Aufruf z.B. im Konstructor platzieren. Allerdings würde dann ja wenn eine Klasse mehrfach instanziiert wird, sich diese Klasse von neuem registrieren wollen. Natürlich könnte ich vorher überprüfen, ob die Klasse schon registriert wurde. Aber evtl. geht das auch eleganter. Jemand eine Idee?
-
Wenn die Fabrik ein Singleton ist, kann man das recht einfach machen:
http://www.drdobbs.com/184403786
-
Ist noch kein Singleton, kann aber noch werden. Ist das nicht auch egal? Mal angenommen meine Factory ist als globale Variable definiert. Wenn ich den von dir genannten Artikel richtig verstehe muss ich also nur
static bool dummy = factory.Register("Control", CreateControl);in z.B. die Control.cpp schreiben. Was aber, wenn die Control.h in diversen anderen Header-Dateien includiert ist. Würde die Klasse dann nicht wieder mehrfach registriert werden? Oder wird genau dies durch das static verhindert?
-
Solange der "Register"-Aufruf nur in der .cpp-Datei drinsteht (frei irgendwo, nicht in einer Methode/Funktion), wird er auch nur einmal aufgerufen.