Mit type_info arbeiten
-
Wie pumuckl schon sagte, sollten die Klassen eigentlich selbst wissen, ob sie für bestimmte Dinge relevant sind. Ansonsten verteilst du Informationen über das Verhalten einer Klasse über das gesamte Programm und das macht einem nach einer gewissen Zeit das Leben schwer.
Falls du Klassen während des Programmlaufs steuern möchtest, ob die Objekte einer Klasse z.B. eine Nachricht gesendet bekommt oder nicht würde ich mal in einem schlauen Buch über Entwurfsmuster nachsehen. Es gibt dafür einige sehr elegante Lösungen.
-
Danke für die Antworten,
die Gewissensbisse hatte ich auch schon.Es ist jedoch folgendes Problem:
Wenn ich von meinen Klassen Objekte erzeuge, dann ist es von Randbedingungen abhängig, wie sie intern ausgeprägt sind d.h. wie die internen Container bestückt sein sollen.
Diese Bestückungs-Information ist erst zur Laufzeit durch die Auswertung eines relationalen Schema entscheidbar.
Dieses relationale Schema ist nicht wie bei Datenbanken verknuepfbar sondern ueber merhdeutige Bitmuster, die eine Art Aussagenmatrix bilden.Ich wollte daher zunächst diese Information von dem relationalen Schema auf ein objektorientiertes Niveau transformieren und das dann den Konstruktoren bzw. die Fabriken vorwerfen.
Aus dem Grund wollte ich in etwa so eine Matrix erstellen, die dann die Konstruktoren bekommen:
map<Klassentyp, map<Randbedingung, list<befuellung>>> matrix;Und dazu wollte ich eigentlich vermeiden, dass ich die String-Bezeichnung oder Nummern der Klassen dort einfüge, sondern direkt die Klasse anhand des Typs darin verwurzele.
-
Also warum du das alles machen willst, habe ich nicht wirklich verstanden. Der Hintergrund interessiert auch nicht wirklich um das Problem überhaupt technisch zu lösen.
Mir kommt es so vor, als ob du eher den Reflections-Mechanismus wie in java benötigst, da du ganz einfach Dinge zur Laufzeit lösen willst. Und hier muß man dich leider enttäuschen: C++ ist knallhart eine Compiler-Sprache. D.h. du mußt als Designer vieles zur Compilezeit lösen, weil es zur Laufzeit fast keine Typinformationen gibt. Das es überhaupt eine Typ-Information gibt ist schon ein Wunder, und selbst das ist von Compiler zu Compiler unterschiedlich, weil die Typinformationen nicht standardisiert sind.
Du mußt dich mit Templates und Polymorphie behelfen, um deine Container zu instanzieren. So wie du es machen willst, wird es nicht funktionieren. Und wenn du Typinformationen zur Laufzeit haben willst, mußt du deine Objekte selbst wissen lassen, was sie sind. Z.B. so:
class obj_info { private: std::string obj_type; int obj_size; // naja, ist jetzt wirklich nur ein Beispiel! public: const std::string& get_obj_type() { return obj_type; } }; class car : private obj_info { public: using get_obj_type(); car() { obj_type = "car"; } };So in etwa...
jedenfalls ist das die sicherste Methode Infos rumzuschleppen. Aber das Instanzieren eines beliebigen Typs zur Laufzeit wird trotzdem nicht funktionieren.
-
Danke für die gute Antwort.
Zunächst möchte ich das Problem einschränken, denn ich möchte nicht zu Laufzeit neue Klassen erstellen.
Die zur Entwurfszeit deklarierten Klassen (also Typen) müssen lediglich verarbeitet werden - ohne in die Klassen einzugreifen, denn diese sollen möglichst einfach sein.Aber es gibt anscheinend keine Chance, eine Typeid-Information zwischenzuspeichern?
Anderseits könnte ich meinen Klassen schon auf ähnliche Weise beibringen, welchen Typ sie haben.
Man könnte z.B. auch nut den Namen via typeid(..).name() statt der ganzen type_info selbst verwenden, der Idee gehe ich mal nach.
Andere Frage:
Was macht das "using" in der Klasse car?
-
Ich glaube du solltest ein anderes Vorgehen wählen.
Wie wärs wenn du aus den Randbedingungen ebenfalls Objekte machst und dann jedes deiner Objekte auf das Randbedingungs-Objekt verweisen lässt, mit dessen Hilfe es erzeugt worden ist (Randbedingungs-Objekt wird einmal bei Programmstart erzeugt und es existiert zu einer Randbedingung immer nur ein Randbedingungsobjekt).
So kannst du die einzlenen Objekte anhand der unterschiedlichen Randbedingungs-Objekte unterscheiden und die Objekte, die du zu den Randbedingungs-Objekten erzeugt hast sind außerdem in der Lage von sich aus ihr Verhalten selbstständig zu bestimmen.
-
hmmm, klingt sauber, aber:
Ich habe weit über 500 Subklassen (Parameter für eine Simulation), die in Kombination mit ca. 20 Hauptklassen (Objekte einer Simulation) auftreten.
Jedes Hauptklassen-Objekt kann nun 0 bis über 500 Objekte der Subklassen akkumulieren, was aber abhängig von der Hauptklasse und der zu simulierenden Variante ist.
Ausserdem scheint es in Zukunft noch zahlreiche Derivate von den 20 Hauptklassen zu geben. Zudem sind die über 500 Parameter erst zur Laufzeit bekannt und können mehrere Ausprägungen haben (Wert, Werteliste, Normkurve (amplitude+Intervall), Messkurven, Zeiten, Boolsche Werte) welche wiederum durch Stöße überlagert werden können ......
(was macht man nicht alles für Geld?)Was ich damit sagen will ist, dass mir RTTI und Templates nicht mehr ausreichen, ich muss tiefer in die Trickkiste greifen ohne dreckige Tricks zu verwenden.
Wegen der Menge und der Dynamik gibt's die Subklassen (Parameter) nicht wirklich als C++-Klassen, sondern als map mit einem String als Schlüssel und einer Ausprägung als reale Klasse.
Ich glaube ihr habt mich auf den richtigen Pfad gebracht:
Ich werde auch die Hauptklassen mit einem String identifizieren und durch ein Fabrik-Pattern bauen lassen, welches dann einen String als Parameter bekommt und dann das possende Hauptobjekt ausspuckt.... auch wenn das auf String-Basis erstmal abartig und ineffektiv aussieht.
Dankeschön.
-
markus.r schrieb:
...
Jedes Hauptklassen-Objekt kann nun 0 bis über 500 Objekte der Subklassen akkumulieren, was aber abhängig von der Hauptklasse und der zu simulierenden Variante ist.
...schon mal was von strategy, decorator oder bridge pattern gehört?
sie bieten eine alternative zu vererbung, und vielleicht auch eine lösung für dein problem mit den vielen unterklassen...Gruß mathik
-
Was du benötigst markus.r ist eine dynamische Struktur (z.B. eine Map in deiner Simulations-Klasse, der sowohl Werte als auch Objekte mit Funktionen, die Teile der eigentlichen Simulation durchführen enthalten kann. Man kann dies sogar so programmieren, dass die Größe der Map variabel ist und dass die eigentliche Simulationsklasse nur noch das Verknüpfen/Verwalten der Map-Elemente übernimmt. Auf diese Weise erhält man einen Baukasten für Simulationen, der sehr flexibel und erweiterbar ist).
-
Danke.
map --> verwende ich bereits intensiv fuer die Subklassen, die quasi durch den Key klassifiziert werden.
Entwurfsmuster --> gute Idee, schaue ich mir gleich an.
-
mathik schrieb:
schon mal was von strategy, decorator oder bridge pattern gehört?
Am Anfang wollte ich Dekoratoren ueber das untere relationale Datenmodel stuelpen. Um Iteration bzw. Mengenoperationen nachzubilden habe ich dann auf sowas wie das Decorator-Muster zurueckgegriffen.
Das alles tellte sich aber als zu komplex dar, da z.B. Mengenaenderungen wie das Loeschen von Objekten neue zu behandelnde Zustände im Datenmodel erzeugten. Es gibt dann mindestens Anzahl_Klassen * Anzahl_Operationen neue Zustaende, die alle behandelt werden müssten.
Das Bridge-Pattern ist dem Decorator grob aehnlich.Daher transformiere ich das relationale Model in ein Objektorientiertes, welches grundsätzlich als Mengenakkumulationsstruktur polymorphe STL-Contrainer und für generische Operationen darauf Template-Methoden verwendet.
Oder gibt es vielleicht einen einfacheren Weg, die Entwurfsmuster einzusetzen?