Allgemeine Frage zu OOP,... Ordnung muß sein
-
sdl-fan-002 schrieb:
Erstelle oder Mische bitte in C/ C++ Listen, Vektoren, etc die verschiedene! datentypen gleichzeitig beinhalten

Wozu braucht man das? Man muss dann trotzdem jeden Typ einzeln handhaben und Fälle unterscheiden (und: es ginge in C++ auch, z.B. mit Boost.Any).

-
Nexus schrieb:
Wozu braucht man das?
Naja, man erhält eine art dynamische struktur...
Btw mag ich C++ lieber als Python, aber Python ist so irre einfach und man kann kleine Ideen in 1/3 der Zeit umsetzen...
-
sdl-fan-003 schrieb:
Btw mag ich C++ lieber als Python, aber Python ist so irre einfach und man kann kleine Ideen in 1/3 der Zeit umsetzen...
Ja, C++ ist halt bei vielen Dingen relativ mühsam und man hat teilweise verhältnismässig lange für kleine Dinge. Das ist aber wieder eine Frage der Übung...
Aber zu deiner anderen Antwort: Das würde mich wirklich interessieren, nicht weil ich einen C++-vs.-Python-Flame anstrebe, sondern weil es mich tatsächlich wundert. Was meinst du mit "dynamischer Struktur"? Wenn einfach alle Typen vorkommen können, wie will man diese spezifisch ansprechen? Man muss ja irgendwo noch Typinformationen abspeichern, und da finde ich es eleganter, die Fälle gleich separat handzuhaben.
-
Nexus schrieb:
Man muss ja irgendwo noch Typinformationen abspeichern, und da finde ich es eleganter, die Fälle gleich separat handzuhaben.
Das ist das wunderbare an Python: Jede Variable kann einen beliebigen Datentypen beinhalten, ohne dafür spezifisch deklariert worden zu sein.
Imo reicht es die Länge der Liste zu ermitteln und dann bis zum Ende durchzuiterieren...Btw Thx Nexus für (nicht nur hier) kreative und informative Antworten, dickes Lob.
-
sdl-fan-002 schrieb:
Erstelle oder Mische bitte in C/ C++ Listen, Vektoren, etc die verschiedene! datentypen gleichzeitig beinhalten

das ist in c++ prinzipell auch möglich. nicht c++ ist das problem, sondern dessen 'dumb user base', die z.b. fragen stellt wie:
Nexus schrieb:
Wozu braucht man das?
-
c++fan.2008 schrieb:
nicht c++ ist das problem, sondern dessen 'dumb user base', die z.b. fragen stellt wie:
Nexus schrieb:
Wozu braucht man das?
Genau solch kritische Fragen, können manchmal das Bewußtsein anregen...
-
sdl-fan-004 schrieb:
Das ist das wunderbare an Python: Jede Variable kann einen beliebigen Datentypen beinhalten, ohne dafür spezifisch deklariert worden zu sein.
Imo reicht es die Länge der Liste zu ermitteln und dann bis zum Ende durchzuiterieren...Aber beim Durchiterieren ist es ja jedes Mal anders, was man mit dem aktuellen Element macht, oder? Wäre es von daher nicht einfacher, von Anfang an jeden Typ einzeln zu behandeln?
Tut mir leid, ich kann es mir nicht ganz vorstellen, vielleicht bin ich als C++-Programmierer auch diesbezüglich etwas zu engstirnig.

sdl-fan-004 schrieb:
Genau solch kritische Fragen, können manchmal das Bewußtsein anregen...
Wie wahr. Aber abgesehen davon hat es sowieso keinen Wert, unregistrierten Benutzern, die nichts zum Thema beitragen und diskutierfreudige Leute als "dumb users" bezeichnen, auch nur irgendeine Beachtung zu schenken.
sdl-fan-004 schrieb:
Btw Thx Nexus für (nicht nur hier) kreative und informative Antworten, dickes Lob.
Ich helfe gerne, und finde es nett, wenn Leute das auch schätzen.

-
Aber beim Durchiterieren ist es ja jedes Mal anders, was man mit dem aktuellen Element macht, oder? Wäre es von daher nicht einfacher, von Anfang an jeden Typ einzeln zu behandeln?
Nicht unbedingt. Wenn sie die gleiche Schnittstelle haben (z.B Ausgabe), kannst du das ganz gut benutzen. C++ hat da ja ein ähnliches Konzept, nennt sich abstrakte Basisklasse.
( Jetzt sollten dir auch ein paar Anwendungsbeispiele einfallen. :))
-
Die Geschichte mit den verschiedenen Datentypen in einem Container ist eben einer der grundlegenden Unterschiede zwischen C++ und Python: statische vs. dynamische Typisierung. beides hat je nach Anwendungsgebiet seine Vor- und Nachteile und seine Daseinsberechtigung.
Bei dynamischer Typisierung kann man wirklich alles in einen Container stopfen. Dafür muss man später bei der Verarbeitung damit rechnen, dass einzelne Elemente eine benötigte Operation nicht anbieten.
Bei statischer Typisierung muss alles vom gleichen Typ sein (bzw. mit polymorphen Zeigern von verwandten Typen), dafür kann man davon ausgehen dass alle Elemente die gleichen Operationen anbieten.Zusammengefasst heißt das in dem Beispiel also: Flexibilität vs. Sicherheit
-
sdl-fan-004 schrieb:
[Das ist das wunderbare an Python: Jede Variable kann einen beliebigen Datentypen beinhalten, ohne dafür spezifisch deklariert worden zu sein.
Imo reicht es die Länge der Liste zu ermitteln und dann bis zum Ende durchzuiterieren...Das nennt man "Weak Typing". Bei C++ wurde bewusst auf "Strong Typing" gesetzt, weil es allgemein die Betriebssicherheit erhöht. Implzite Konvertierungen können z.B. ziemlich böse sein, wenn man nicht aufpasst und sich z.B. verschreibt.
So ziemlich auf die Spitze wird das Strong Typing in Ada getrieben, wo man u.U. Integers nicht einander zuweisen kann.
Beispiel:type Decibel_Type is new Float; --Typ fuer Pegel in dB type Frequency_Type is new Float; --Typ fuer Frequenzen in Hz Freq : Frequency_Type := 0.0; --Deklaration/Initialisierung Level : Decibel_Type := 10.0; --Deklaration/Initialisierung Freq := Level; --Versuch einer Zuweisung, aber Frequenzen != Pegel -> Error Freq := Frequency_Type(Level); -- Typecast. Das geht, aber man muss dem Compiler extra sagen, dass man solchen Unsinn machen willMan kann also z.B., wenn man es auf die Spitze treibt, für verschiedene Maßeinheiten unterschiedliche Typen definieren. Im obigen Beispiel sind beide Typen zwar Float, aber eben trotzdem nicht gleich. Warum das, trotz des höheren Schreibaufwands ein Vorteil sein kann, sollte wohl klar sein, vor allem, wenn es sich um ein Interface handelt, dass von vielen Programmierern benutzt wird.
Das Typsystem von C++ ist nicht ganz so streng, aber auf jeden Fall schon mal deutlich sicherer als irgendwelche Sprachen mit völlig loser Typisierung.
-
du sagst, das Typsystem in C++ sei nicht ganz so streng, das kann man so oder so sehen. Es ist nur nicht so einfach, einen neuen Typen zu erschaffen, der den gleichen Wertebereich hat wie ein anderer Typ. Dein Beispiel sähe in C++ etwa so aus:
struct Decibel_Type { float value; explicit Decibel_Type(float f) : value(f) {} operator float() {return value; } }; struct Frequency_Type { //analog }; Frequency_Type Freq = 0.0f; Decibel_Type Level = 10.0f; Freq = Level; //Versuch einer Zuweisung, aber Frequenzen != Pegel -> Error Freq = Frequency_Type(static_cast<float>(Level)); // Typecast. Das geht, aber man muss dem Compiler extra sagen, dass man solchen Unsinn machen will(den ganzen privtae/public-krams und andere Dinge mal außer acht gelassen)
-
pumuckl schrieb:
[...]
Jo, aber Dein Beispiel lässt problemlos sowas zu:
float unsinn = Freq + Level; //oder sowas Frequency_Type Freq(0.0f); Decibel_Type Level(Freq);In Ada würde auch das nicht gehen. Mal ganz zu schweigen vom Aufwand den man für Zuweisungen treiben muss. Das würden dann zig Float-Wrapper werden, und was man von POD-Wrappern zu halten hat, sollte wohl klar sein.
Beispiel:Decibel_Type level(0.0f); Decibel_Type inc(3.0f); level = level + inc; //geht nichtPS: Das erinnert mich etwas an den Nachbau von OO in C. Das sind Features, die hat die Sprache einfach nicht. Man kann es nachbauen, aber das ist sehr fehleranfällig und mühsam. Kosten/Nutzen stehen nicht im gesunden Verhältnis zueinander.
-
Mein Beispiel war nur mal eben hingerotzt. Es gibt durchaus Möglichkeiten, die Konvertierungsoperatoren wegzulassen bzw. zu ersetzen, und arithmetische Operatoren zu implementieren ist in dem Fall bestenfalls eine Anfängerübung. Ich habe auch nicht behauptet, dass all das besonders schön oder elegant aussähe, ich wollte lediglich darauf hinaus, dass derartige Wrapper als Typsicherheits-Schutz möglich sind, aber eben nicht so schnell zu erschaffen wie in Ada.
Im Übrigen gabs grade für dein Beispiel (physikalische Werte) vor einiger Zeit ein Beispiel hier im Forum, wie man eine entsprechende Bibliothek aufbauen könnte:
template <int length_dim, int time_dim, int weight_dim> class PhysicalUnit { double value; //in kg/m/s - System //... }; //Diverse Operatoren... //typedefs für gebraeuchliche Groessen: typedef PhysicalUnit<1,0,0> Length; typedef PhysicalUnit<2,0,0> Area; typedef PhysicalUnit<1,0,-1> Velocity; typedef PhysicalUnit<1,0,-2> Acceleration; typedef PhysicalUnit<0,0,-1> Frequency; //... struct Units { const static Frequency Hz; //Frequency(1) const static Length cm; //Length(0.01) const static Acceleration grav; //Acceleration(9.81) const static Length inch; //Length(0.0249) }; int main() { Length breite = 5 * Units::cm; Length laenge = 10 * Units::inch; Area flaeche = breite * laenge; }Damit gehen dann solch sinnfreie Rechnungen auch nicht mehr.
-
Ich habe ja auch gar nicht gesagt, dass es überhaupt nicht geht. Es ist nur sehr mühsam und produziert zusätzlichen Code. In Ada werden einfach die Typnamen verglichen. Das ist schon einfacher.
Du solltest vielleicht noch auf boost.units verweisen, wenn Du da schon abguckst.