Unterschiedliche Datentype zur Laufzeit hinzufügen
-
Hallo liebe Leute!
Für mehrere Klassen benötige ich die Möglichkeit zusätzliche Daten hinzufügen zu können. (int, double, string, boolean, objecte)
Mein Problem, ich bin nicht sicher welches der beste Weg ist, daher liste ich die Varianten auf.
Der Code ist nur zum zeigen als allgemeiner Ansatz schnell mal hingetippt!
Lesen, Schreiben und prüfen will ich primär über Templats erledigen// Varinate 1 -> 1 Container je Datentype // Für jeden möglichen Datentype muss ich einen Container angelegen (hier map) // Objecte sollten von einer Basisklasse abgeleite werden und weniger Container zu benötigen std::map<int, int> intMap; std::map<int, std::string> strMap; std::map<int, Object> objMap; // ... Weiter map's für andere Datentypen// Variante 2 -> boost/any oder boost/variant // Hier wäre nur ein Container erforderlich // Es gibt natürlich Einschränkungen seitens boost bezüglich der Datentypen std::map<int, boost::any> AnyMap; // oder std::map<int, boost::any> variantMap;// Variante 3 -> Union // Hier wäre nur ein Container erforderlich // Objecte sind ja hier nicht möglich, also ein 2. Contaioner für Objecte union DatenUnion { int iWert; double dWert; long lWert; // Weitere Datentypen }; std::map<int, DatenUnion> uMap; std::map<int, std::string> objMap;Jetzt meine Fragen bzw. Vermutungen:
1.) boost::any und boost::varinat
Hier wird mit Cast's gearbeitet!?
keine Typen-Prüfung durch Compiler2.) Union
Die schnellste Lösung
keine Typen-Prüfung durch Compiler3.) Mehrere Conatiner
Typen-Prüfung durch Compiler
Höherer Speicherverbrauch4.) Andere Lösungen
Sehe ich nicht, hat hier wer eine bessere Alternative????Derzeit stehe ich wohl etwas auf der Leitung und bitte daher um Hilfe.

Mit liebem Gruß
Eduard
-
Hängt vom Rest des Projekts ab.
-
volkard schrieb:
Hängt vom Rest des Projekts ab.

@EduardH:
Zeig mal wie das Interface aussehen soll, über das du diese Funktionalität ansprechen möchtest.
-
Als Ergebnis soll eine Framework entstehen, welches den Benutzer anbietet:
z.B:
1.) Freie Erstellung von Objecten -> Definition der Attributnamen und -Type
2.) Erstellen von Regeln -> z.B: if (O1.Preis > O2.Preis) then O1.Gewicht = O2.Gewicht
3.) Dateneingabe in den Objecten
4.) Abfragen zu den Daten
5.) Simulation (Soetwas wie selbstständiges Agieren und sehen wie sich die Daten ändern)
6.) SourceCode generator für Objecte (Wunschdenken
)Eine fertige Schnittstelle habe ich noch nicht erstellt, da ich noch am Anfang stehe
Aber so als erster Ansatz (Const, & und Co fehlen!)// Diese Class beinhaltet alle Attribute welche zur Laufzeit eingefügt werden class AContainer { private: // Die Container boost::any, Union, .... public: // Fügt ein neues Attribut hinzu oder überschreibt bestehendes template <class T> bool setAtt(int Key, T &Att){} // löscht das Attribut template <class T> bool killAtt(int Key){} // Prüft ob Attribut existiert template <class T> bool existsAtt(int Key){} // Liefert den Wert des Attributs template <class T> T getAtt(int Key){} // Extrahiert die Daten in den Sicherungsbuffer template <class T> bool SaveMe(std::vector<T> Buffer){} // Lade die Daten aus dem Sicherungsbuffer template <class T> bool LoadMe(std::vector<T> Buffer){} };
-
Und wieso willst du das in C++ programmieren? Stehst du auf Schmerzen?
Nimm Lua oder Python oder sowas.
-
hustbaer schrieb:
Und wieso willst du das in C++ programmieren? Stehst du auf Schmerzen?
Nimm Lua oder Python oder sowas.
Lua, Python und Java mag ich einfach nicht!
Mit C++ finde ich es nicht so schlimm und Schmerzen bin ich von Assembler(x86) und Jiu Jitsu gewöhnt

Ich hatte auch noch eine Variante über Entwurfsmuster -> Dekorierer und
eine Variante über ein globale AttributClasse.
Diese sind mir aber zu langsam sprengen die Kapselung.Daher meine Frage.
-
Was hustbear meint, ist nich, dass C++ an sich SChmerzen verursacht, sondern genau in deinem Fall. In C++ Ist es einfach eine schlechte Idee, deinen Ansatz genauso umsetzen zu wollen, für sowas sind andere Sprachen gedacht.
Wer in C++ nach Containern für verschiedene Typen fragt, der hat ein ganz schweres Design Problem in seinem Projekt.
-
DMM schrieb:
Was hustbear meint, ist nich, dass C++ an sich SChmerzen verursacht, sondern genau in deinem Fall. In C++ Ist es einfach eine schlechte Idee, deinen Ansatz genauso umsetzen zu wollen, für sowas sind andere Sprachen gedacht.
Wer in C++ nach Containern für verschiedene Typen fragt, der hat ein ganz schweres Design Problem in seinem Projekt.C++ finde ich auch nicht schwerzhaft

Hmmm..., wenn ich das richtig verstehe bedeutet das in Summe:
Es ist also nicht verwunderlich das ich mir über diverse Lösungen den Kopf zerbrechen.
Um die variablen Parameter komme ich nicht herrum, leider!Mögliche Lösungen wären also:
a: Ich suchen mir eine Lösungen aus
oder
b. Ich wechsle auf eine nicht streng typisierte Sprache?
-
Erklär mal, was du überhaupt tun möchtest. Das klingt mir stark nach schlechtem Design.
-
C und C++ verlangen eine Deklaration der eingesetzten Datentypen. In C++ hast du die Möglichkeit zur Überlagerung und kannst damit einiges anfangen. Bei Klassen kann das schnell zur Knochenarbeit werden. Also teile erst einmal genau mit, was du vorhast und brauchst.
-
Du weißt schon, das du Lua wunderbar in C++ einbetten kannst? Du mußt nicht dein gesamtes Projekt in Lua machen, sondern nur den zu Lua wunderbar passenden Teil. Und C++ kannst du für den Rest nutzen.
-
EduardH schrieb:
Als Ergebnis soll eine Framework entstehen, welches den Benutzer anbietet:
z.B:
1.) Freie Erstellung von Objecten -> Definition der Attributnamen und -Type
2.) Erstellen von Regeln -> z.B: if (O1.Preis > O2.Preis) then O1.Gewicht = O2.Gewicht
3.) Dateneingabe in den Objecten
4.) Abfragen zu den Daten
5.) Simulation (Soetwas wie selbstständiges Agieren und sehen wie sich die Daten ändern)
6.) SourceCode generator für Objecte (Wunschdenken
)
Eine fertige Schnittstelle habe ich noch nicht erstellt, da ich noch am Anfang steheDann fängst Du mit dem falschen Ende an, fürchte ich.
- Schreibe einen mathematischen Parser, der nur double berechnenm kann.
- Schreibe einen neuen, der double und int kann.
- Bastele weitere Schlüsselwörter if/the, while, print ein.
- Wenn der Parse-Baum aus polymorphen C++-Objekten besteht, ist 6.) extrem einfach nachzurüsten.
-
314159265358979 schrieb:
Erklär mal, was du überhaupt tun möchtest. Das klingt mir stark nach schlechtem Design.
Ah, die Design Keule mal wieder. Ist das Dot's Zweitnick?
-
BAUMKOPFHOLZFAUST schrieb:
314159265358979 schrieb:
Erklär mal, was du überhaupt tun möchtest. Das klingt mir stark nach schlechtem Design.
Ah, die Design Keule mal wieder. Ist das Dot's Zweitnick?
Wer ist Dot?
Die Design-Keule ist hier angebracht.
-
volkard schrieb:
Wer ist Dot?
Ein User mit dem Nick 'Dot', Watson!
-

volkard schrieb:
EduardH schrieb:
Als Ergebnis soll eine Framework entstehen, welches den Benutzer anbietet:
z.B:
1.) Freie Erstellung von Objecten -> Definition der Attributnamen und -Type
2.) Erstellen von Regeln -> z.B: if (O1.Preis > O2.Preis) then O1.Gewicht = O2.Gewicht
3.) Dateneingabe in den Objecten
4.) Abfragen zu den Daten
5.) Simulation (Soetwas wie selbstständiges Agieren und sehen wie sich die Daten ändern)
6.) SourceCode generator für Objecte (Wunschdenken
)
Eine fertige Schnittstelle habe ich noch nicht erstellt, da ich noch am Anfang steheDann fängst Du mit dem falschen Ende an, fürchte ich.
- Schreibe einen mathematischen Parser, der nur double berechnenm kann.
- Schreibe einen neuen, der double und int kann.
- Bastele weitere Schlüsselwörter if/the, while, print ein.
- Wenn der Parse-Baum aus polymorphen C++-Objekten besteht, ist 6.) extrem einfach nachzurüsten.Naja ich fing bei folgenden Ende an
Der Benutzer kann sich sein Attribute selbst definieren.
z.B: Datentype, Minwert, MaxWert, Name, Anmerkung und automatische id Vergabe.
Diese Informationen sind als leicht als Object zu definieren und liegen in einer map um über die id zugreifen zu können.Aus den definierten Attributen baut er jetzt sein Object zusammen.
Hier ist mein einziges Problem in der Speicherung, daher meine verschiedenen Ansätze. Vieles lässt sich ja einfach über templats erledigenMit allen anderen Punkten (2-6) gibt es kein Problem!!!!
Die Idee bereits nur double zu berechnen, bringt mich auf folgendes

Die Anzahl der möglichen Datentypen kann auf 3 reduzieren werden
map(double)
mab(string)
map(object)Das so zumachen lag mir fern!
Historisch bedingt (2k Ram war mal viel) bin ich ein Sparefroh bezüglich Speicher und Laufzeit.Besten Danke!
Eduard@314159265358979
Die Design Keule sollte erst ausgepackt werden, wenn ein Design erstellt wurde!Nicht alles was flexibel/generisch sein soll, ist auch ein Fehler.
-
Ich habe dein Design lediglich in Frage gestellt, nicht gesagt dass es schlecht ist. Und für mich sieht das immer noch komisch aus, ich kann aber auch mit deiner Beschreibung nichts anfangen.
-
@314
"Verstehe ich nicht" => "klingt nach schlechten Design"
1A Logik
-
314159265358979 schrieb:
Ich habe dein Design lediglich in Frage gestellt, nicht gesagt dass es schlecht ist. Und für mich sieht das immer noch komisch aus, ich kann aber auch mit deiner Beschreibung nichts anfangen.
Ich versuche es mal anders zu beschrieben.
Es gibt ein Basisklasse Object, als einfaches Beispiel:
class Object { private: std::string Vorname; std::string Nachname; std::string Geburtsdatum; public: bool setVorname(std::string){} // und was so alles benötigt wird }Diesem Object sollen zur Laufzeit neue Variablen/Member hinzugefügt werden.
Die Datentypen sind zur Compilezeit bekannt!
Die Anzahl der Member ist zur Compilezeit nicht bekannt!Die erlaubten Datentype sind in meinem Fall:
int
bool
double
std::string
Referencen auf das Basisobject bzw. abgeleitete Objecte der BasisDies würde, da C++ streng typisiert ist, für jeden Datentype einen eigenen Container erfordern.
Für jeden möglichen Datentype muss ein Container in die class integriert werden
Templates helfen mir den geschriebenen Code zu vereinfachen, die Anzahl der Container bleibt aber gleich.Die Basisklasse Object würde verreinfacht so aussehen
class Object { private: std::string Vorname; std::string Nachname; std::string Geburtsdatum; std::map<int, int> intMap; std::map<int, bool> booMap; std::map<int, double> booMap; std::map<int, std::string> strMap; std::map<int, Object> objMap; public: bool setVorname(std::string){} // und was so alles benötigt wird }Daher habe ich mir mehrere Lösungsansätze überlegt um dennoch neue Member hinzuzufügen ohne gleich eine Container-Inflation zu erhalten
Und diese Lösungsansätze gepostet mit der Bitte um Hilfe!War das jetzt verständlich?
-
volkard schrieb:
BAUMKOPFHOLZFAUST schrieb:
314159265358979 schrieb:
Erklär mal, was du überhaupt tun möchtest. Das klingt mir stark nach schlechtem Design.
Ah, die Design Keule mal wieder. Ist das Dot's Zweitnick?
Wer ist Dot?
Die Design-Keule ist hier angebracht.Das bin wohl ich. Und nein, 314159265358979 bin nicht ich. Aber ich hätt die Design Keule auch ausgepackt bzw. tus gleich mal.
@EduardH: deiner Beschreibung nach find ich dass dein Vorschlag prinzipiell mal eine Lösung ist, wobei ich statt einer map einfach einen vector verwenden würde falls es sich einrichten lässt dass die keys aufsteigende Integer sind. Allerdings find ich das Problem an sich ein wenig merkwürdig, warum genau musst du denn diese Daten hinzufügen, was soll mit denen mal geschehen? Ein Objekt das für sämliche Member Getter und Setter anbietet ist imo irgendwie was ziemlich kaputtes.