Warum hat C++ so eine aufwendige Syntax?



  • Prognose schrieb:

    ...Im Jahr 2010 noch mit Headern und include guards rumfrickeln is einfach nur noch lächerlich. 👎

    Hä ?
    Was ist DAS denn für eine Aussage ?
    Header sind eine erstklassige Methode, ein Interface zu beschreiben und der Entkopplung und dass es eine ODR gibt, ist auch kein Nachteil.....
    😕

    Gruß,

    Simon2.



  • Simon2 schrieb:

    - Konsolenfenster schließen sich nicht mehr automatisch

    lol 😃
    Wenn ich ne Konsole öffne, dann bleibt die auch offen. Mach doch mal Windowtaste + R -> cmd ... die bleibt offen.



  • Simon2 schrieb:

    Stattdessen kommen immer nur so Sachen wie "Pointer sind gefährlich" oder "Operatorüberladung braucht man nicht"... 🙄 :p 😃

    Ich habe da auch noch so ein paar Schnitzer, über die ich gestolpert bin. Die hier aber nie genannt wurden.

    Warum werden solche Dinge nicht genannt? Weil die Leute nie intensiv mit C++ gearbeitet haben aber trotzdem ne große Fresse haben und die uralten Argumente, die sie mal gelesen/gehört haben, bringen. Würden sie wirklich mit C++ gearbeitet haben, würden sie ganz andere Themen auf den Tisch bringen.



  • Simon2 schrieb:

    - templates könnten durchschaubarer sein (friends, Basisklassen, Anforderungen an instantiierende Klassen, ...)

    ja, die template-syntax ist ziemlich gruselig, aber man kann nicht C++ allein die schuld geben. oft sieht man, dass C++ user das ganze noch verschlimmern, indem sie einbuchstabige bezeichner wählen und alles in eine zeile quetschen, wie hier erst geschehen: http://www.c-plusplus.net/forum/viewtopic-var-t-is-188053-and-highlight-is-.html
    wer solchen code schreibt, für den wäre vielleicht APL besser geeignet 😉

    Simon2 schrieb:

    - Grenze zu primitiven Typen aufheben (ableitbar, Operatoren überladen, ...)

    genau. das fände ich auch gut. wenn schon op-overloading vorhanden ist, dann bitteschön für jeden operator und jeden typ.

    Simon2 schrieb:

    - "double dispatching"

    C++ user haben schon genug probleme mit RTTI, typeid o.ä. jedesmal wenn hier einer sowas verwendet, werden ihm 'designfehler' vorgeworfen. die sprache kennt zwar OOP, aber die C++ 'userbase' will irgendwie nichts davon wissen.
    'double dispatching' würden sie, nehme ich an, erst recht ablehnen.

    Simon2 schrieb:

    - compilerübergreifendes Lib- und Klassen-Binärformat

    es gibt für libs einige verbreitete binärformate wie elf/dwarf usw, allerdings enthalten libs immer maschinencode und sind daher nicht zwischen verschiedenen prozessoren austauschbar. was würde das also bringen?

    Simon2 schrieb:

    - Konsolenfenster schließen sich nicht mehr automatisch

    huch? das ist doch sache des betriebssystems. schreib' als letzte anweisung in deine 'main' ein C++-standardkonformes 'while(true);' dann bleibt die konsole offen.

    🙂



  • 1967 Summer Of Love schrieb:

    Simon2 schrieb:

    - Konsolenfenster schließen sich nicht mehr automatisch

    lol 😃
    Wenn ich ne Konsole öffne, dann bleibt die auch offen. Mach doch mal Windowtaste + R -> cmd ... die bleibt offen.

    Undertaker schrieb:

    ...

    Simon2 schrieb:

    - Konsolenfenster schließen sich nicht mehr automatisch

    huch? das ist doch sache des betriebssystems. schreib' als letzte anweisung in deine 'main' ein C++-standardkonformes 'while(true);' dann bleibt die konsole offen.

    🙂

    Anscheinend ist meine Ironie nicht als solche zu verstehen. 😃

    Gruß,

    Simon2.



  • Undertaker schrieb:

    Simon2 schrieb:

    - Grenze zu primitiven Typen aufheben (ableitbar, Operatoren überladen, ...)

    genau. das fände ich auch gut. wenn schon op-overloading vorhanden ist, dann bitteschön für jeden operator und jeden typ.

    👍 EBEN !

    Undertaker schrieb:

    Simon2 schrieb:

    - "double dispatching"

    C++ user haben schon genug probleme mit RTTI, typeid o.ä. jedesmal wenn hier einer sowas verwendet, werden ihm 'designfehler' vorgeworfen. die sprache kennt zwar OOP, aber die C++ 'userbase' will irgendwie nichts davon wissen.
    'double dispatching' würden sie, nehme ich an, erst recht ablehnen. ...

    Also gerade WEIL ich das explizite Rumhantieren mit typeids ablehne (sehr fehleranfällig und wartungsunfreundlich) würde ich ein vernünftiges double dispatching durch die Sprache befürworten !
    Erst dadurch, dass es kein double dispatching gibt, muss man mit TypeIDs (seien es nun solche der eingebauten RTTI oder selbstgestrickte) was zusammenfummeln.
    OOP bedeutet für mich nicht RuntimeTTI, sondern ich bin froh über alles, was mir der Compiler abnimmt.
    In mir hast Du also einen typischen Vertreter der Haltung erwischt, die Du beklagst. 😃

    Undertaker schrieb:

    Simon2 schrieb:

    - compilerübergreifendes Lib- und Klassen-Binärformat

    es gibt für libs einige verbreitete binärformate wie elf/dwarf usw, allerdings enthalten libs immer maschinencode und sind daher nicht zwischen verschiedenen prozessoren austauschbar. was würde das also bringen?

    Es würde bringen, dass man auf derselben Plattform mit unterschiedlichen Compilern arbeiten könnte:
    - Verschiedene Entwickler im Projekt können ihren Favoriten nehmen
    - ich kann jede Fremdlib einbinden
    - Wenn unsere Firma auf eine neue Compilerversion wechselt, brauche ich keinen kompletten Rebuild
    - "binäre Serialisierung" (im Javasinne) wäre sinnvoll möglich.
    - ...
    Die Grenze zu einer anderen Plattform halte ich für nicht so entscheidend, weil
    - heutzutage nicht wirklich soooo viele Plattformen für eine Anwendung gebraucht werden und
    - bei einer Sprache, die "durchkompiliert" (was ich gut finde) sowieso ein Binäraustausch nicht besonders sinnvoll wäre.
    Klar, wenns das "dazu" gäbe (ohne wesentliche Nachteile), fände ich es gut, aber die Compilerunabhängigkeit wäre mir deutlich wichtiger.

    Gruß,

    Simon2.



  • Artchi schrieb:

    Warum werden solche Dinge nicht genannt?

    Vielleicht weil die Miniproblemchen, die Du zulässt keine Sau interessieren? Vielleicht würdest Du die anderen Probleme auch erkennen, wenn Du Deine rosarote Brille abnähmest und aufhören würdest Dir hier auf die Schulter zu klopfen:

    Weil die Leute nie intensiv mit C++ gearbeitet haben aber trotzdem ne große Fresse haben und die uralten Argumente, die sie mal gelesen/gehört haben, bringen.

    👎



  • Undertaker schrieb:

    Simon2 schrieb:

    - compilerübergreifendes Lib- und Klassen-Binärformat

    es gibt für libs einige verbreitete binärformate wie elf/dwarf usw, allerdings enthalten libs immer maschinencode und sind daher nicht zwischen verschiedenen prozessoren austauschbar. was würde das also bringen?

    Er meint sicherlich innerhalb einer Plattform. Also wenn ich unter Win32 bin, würde ich gerne in MSVC statische Libs nutzen, die jemand mit seinem g++ gebaut hat. Alleine die Bytegröße der nativen Datentypen unterscheidet sich von Compiler zu Compiler auf ein und der selben Plattform. MS hat unter Windows zumindest mit den COM-Specs eine absolute Vorgabe gemacht. Nützt aber C++ nichts, da die COM-Specs C-basiert sind... oder wie man sowas auch immer klassifizieren will.

    Aber der C- und C++-Standard macht keine Vorgaben in dem Bereich, weil er nur eine Sprache und keine Plattform beschreibt. Also werden wir da auch nichts erwarten können. Aber um ehrlich zu sein, ich habe da kein Problem mit der aktuellen Situation. Wenn ich eine Library anbiete, habe ich mehrere Möglichkeiten:

    • ich biete die Lib als Source an mit einem Buildfile (vorzugsweise Compiler-übergreifendes Format, z.B. bjam). Hier stellt Opensource den kleinsten Aufwand für beide Seiten (Kunde und Anbieter)
    • bei Closedsource baue ich die Lib mit den verbreitesten Compiler vor (bzw. was die Kunden wünschen, ich muß ja nicht 10 Compiler kaufen, wenn meine Kunden nur Libs für MSVC und MinGW wünschen)
    • ich biete bei Closedsource meinen zahlenden Kunden die Lib im Source an, falls ich kein Bock habe zu viele Compiler zu besorgen. 😉

    Hier sehe ich also das kleinste Problem. Bedarf sehe ich weiterhin im Bereich der Sprache und des Buildverfahrens.



  • Simon2 schrieb:

    - Grenze zu primitiven Typen aufheben (ableitbar, Operatoren überladen, ...)

    Ja, und dann ne Performance wie Javascript. 🙄



  • w schrieb:

    Simon2 schrieb:

    - Grenze zu primitiven Typen aufheben (ableitbar, Operatoren überladen, ...)

    Ja, und dann ne Performance wie Javascript. 🙄

    Das mein abgeleitetes Simon2int evtl. nicht mehr die Performance eines ints hat, leuchtet mir ja ein, aber warum sollte int langsamer werden ?

    Gruß,

    Simon2.



  • Simon2 schrieb:

    w schrieb:

    Simon2 schrieb:

    - Grenze zu primitiven Typen aufheben (ableitbar, Operatoren überladen, ...)

    Ja, und dann ne Performance wie Javascript. 🙄

    Das mein abgeleitetes Simon2int evtl. nicht mehr die Performance eines ints hat, leuchtet mir ja ein, aber warum sollte int langsamer werden ?

    Gruß,

    Simon2.

    Wenn du einen Simon2int haben willst, warum willst du diesen von int ableiten? Damit du operator+(int,int) benutzen kannst? Wenn deiner Klasse dieser genügt, dann reicht doch auch eine implizite Umwandlung von Simon2int zu int mit einem operator int in deiner Simon2int Klasse.

    Ich kann darin keinen Vorteil erkennen und für mich macht das so viel Sinn wie das Überladen der Scope-Operatoren.



  • Simon2 schrieb:

    Das mein abgeleitetes Simon2int evtl. nicht mehr die Performance eines ints hat, leuchtet mir ja ein, aber warum sollte int langsamer werden ?

    Dann soll int ein primitiver Typ bleiben (also + -> add ax, 123) und zusätzlich so ne Art Klasse sein, von der man ableiten kann (also überschriebenes + -> Funktionsaufruf)? Das ist ja noch kaotischer und komplizierter. Naja, in C++ kann man ja auch ints als Exception werfen...



  • lolz schrieb:

    ...Wenn du einen Simon2int haben willst, warum willst du diesen von int ableiten? Damit du operator+(int,int) benutzen kannst?....

    Warum will man überhaupt ableiten ?

    Andersherum wird für mich ein Schuh draus: Warum darf man von allem Ableiten aber von int&Co nicht ? Das schränkt IMO die Möglichkeiten (z.B. von Metaprogrammierung) unnötig ein.
    Ja, ja, ja, ich weiß: Performance, C-Compliance, .... die historischen Ursachen kenne ich.
    Trotzdem würde ich mir eine größere Konsistenz wünschen.

    Gruß,

    Simon2.



  • w schrieb:

    ...Dann soll int ein primitiver Typ bleiben (also + -> add ax, 123) und zusätzlich so ne Art Klasse sein, von der man ableiten kann (also überschriebenes + -> Funktionsaufruf)? Das ist ja noch kaotischer und komplizierter. Naja, in C++ kann man ja auch ints als Exception werfen...

    1.) Die Umsetzung in eine konkrete Maschinensprache haben IMO nichts in einem Sprachkonzept zu suchen.

    2.) Was soll denn daran chaotisch und kompliziert sein ? Stören Dich auch die vtables, die man beim Übergang C->C++ hinzugekommen sind ?

    3.) Insgesamt hinterlassen Dein Stil und Deine Argumentation(sweise) eher den Eindruck als wolltest Du nur rumpöbeln - weniger nach Interesse an einer Diskussion.

    Gruß,

    Simon2.





  • w schrieb:

    Dann soll int ein primitiver Typ bleiben (also + -> add ax, 123) und zusätzlich so ne Art Klasse sein, von der man ableiten kann (also überschriebenes + -> Funktionsaufruf)?

    wenn man es inline ausführt, würde, so es möglich wäre, bei:

    inline int operator+(const int& a, const int& b)
    {
    	return a+b;
    }
    

    exakt die gleiche befehlsfolge rauskommen wie "a+b;".
    wozu man das tatsächlich braucht kann, außer um ein paar konvertierungsprobleme zu lösen, sei mal dahin gestellt.

    w schrieb:

    Das ist ja noch kaotischer und komplizierter. Naja, in C++ kann man ja auch ints als Exception werfen...

    wieso sollte man keine ints werfen können? stört doch keinen, wenn man nur einen fehlercode zurückgeben will, da braucht man doch nicht erst großartig eine klasse für zu erzeugen.



  • ghorst schrieb:

    w schrieb:

    Dann soll int ein primitiver Typ bleiben (also + -> add ax, 123) und zusätzlich so ne Art Klasse sein, von der man ableiten kann (also überschriebenes + -> Funktionsaufruf)?

    wenn man es inline ausführt, würde, so es möglich wäre, bei:

    inline int operator+(const int& a, const int& b)
    {
    	return a+b;
    }
    

    exakt die gleiche befehlsfolge rauskommen wie "a+b;".
    wozu man das tatsächlich braucht kann, außer um ein paar konvertierungsprobleme zu lösen, sei mal dahin gestellt.

    Und woher soll der Compiler jetzt wissen, dass du hier keine Endlosrekursion bauen willst, sondern er hier den Maschienencode für eine Addition zwischen zwei Integern einfügen soll?



  • gute frage. nächste frage.
    kein ahnung. müsste man vllt einen satz pragmas drumherum setzen. war auch nur als beispiel gedacht und ist in c++ auch nicht zulässig, wobei ein rekursiver operatoraufruf schon ulkig wäre.



  • warum in aller welt will jemand von einem value type ableiten? die sind nicht zum ableiten gedacht.

    es gibt ein paar dirty hacks wo man es gerne macht - aber dann will man eher code reuse betreiben als ein sauberes design haben (was natürlich durchaus legitim sein kann). aber int hat keinen code den ich reusen könnte wenn ich davon ableite.

    in so einem fall kommt eher eine has-a oder implemented-in-terms-of beziehung besser.

    Der einzige Ansatz der mir hier einfällt wäre der C#/Java Ansatz mit int und Integer. Doch sehen wir uns an wofür man Integer verwendet:
    um ein Objekt zu haben dass von Object ableitet.

    Wofür braucht man das? Um es in einen Polymorphen Container zu stecken. Wie oft braucht man polymorphe container von Object? Also ich habe soetwas noch nie gebraucht - es widerspricht dem OOD. In Java hat man Container of Object ja nur gehabt (wohl gemerkt: gehabt!) weil es keine templates gab. diese container waren furchtbar, deshalb hat man dann ja auch generics implementiert.

    also kann mir mal jemand kurz erklären wann er je von Integer geerbt hat? Oh, warte - die Klasse ist ja final... Ne, aber Spaß beiseite: gebt mir ein Beispiel wo es sinnvoll ist von int zu erben.

    Bedenkt: int hat kein public interface dass ich sinnvoll erben kann. Ich komme so nie in eine sinnvolle is-a beziehung. weil mir die polymorphie fehlt.

    das dagegen sinn macht, wäre ein auto-boxing für 4.sqrt() == 2
    sowas finde ich wunderschön. aber auch hier will man nicht von int erben.

    was in c++ eine katastrophe ist, sind die compile times und die unterschiedlichen compiler. das ist wirklich ein enormes problem von c++. ein weiteres ist, dass es keine standardisierte library gibt. boost ist zwar ein schritt in die richtige richtung, aber man braucht dauernd extrene libraries. das problem dabei ist: es gibt soviele, dass man idR nicht davon ausgehen kann dass im Team genug Know How mit der lib da ist. ergo hat man dauernd lernphasen die man zB in Java nicht hat. Jeder der in Java programmiert hat zu wissen wie man Threads erstellt, suspended, resumed,... aber nicht jeder C++ programmierer kennt sich mit pthreads aus - er kennt sich zwar mit threads generell aus, aber diese bestimmte lib muss ihm noch nicht untergekommen sein. weiters gibt es ja wieder kompatibilitaetsprobleme mit den libs zu den compilern...

    also wenn jemand c++ kritisieren will - das ist der richtige ansatz 😉



  • eine patchwork sprache halt 😃


Anmelden zum Antworten