C zu C++ - Einfacherer Übergang?
-
namespace invader schrieb:
Und auch wenn man keine Exceptions verwenden will, zwingt einen allein die Tatsache, dass es in C++ Exceptions gibt, trotzdem dazu, ständig darauf zu achten dass der Code den man schreibt Exception-safe ist.
Die Standardbibliothek ist ziemlich defensiv, was Exceptions anbelangt. Wenn du selbst keine Exceptions und keine Bibliotheken mit Exceptions verwendest, kann also nicht viel passieren. Abgesehen davon ist Exceptionsicherheit fast gratis, wenn man RAII verwendet. Man muss ja nicht C in C++ programmieren.
Ich weiss zwar nicht, wie oft das bereits erwähnt wurde, aber in anderen Programmiersprachen hat man das Problem ebenfalls. Nur Speicher wird einem aufgeräumt, andere Ressourcen muss man selbst sichern. Und gerade in Sprachen wie Java, die an jeder Ecke eine Exception werfen und mit
finally
zu manueller Freigabe zwingen, ist das nicht besonders lustig.namespace invader schrieb:
Man verschwendet also Zeit, nur um sich um Sprachfeatures zu kümmern, die man gar nicht nutzen will. Im Prinzip das selbe wie die Kopierkonstruktoren und Zuweisungsoperatoren, für die man ständig Zeit opfert obwohl man sie eigentlich gar nicht braucht.
Schön, dass du gerade ein Beispiel bringst, auf das das Gegenteil zutrifft. Kopierkonstruktoren und Zuweisungsoperatoren musst du in den wenigsten Fällen selbst implementieren – nämlich dann, wenn du eine spezifische Kopiersemantik möchtest. In den meisten Fällen tun aber die eingebauten Funktionen das Richtige.
-
@namespace invader
Wenn man keine Exceptions nutzen will, dann nutzt man einfach keine Exceptions und muss sich darüber überhaupt keine Gedanken machen. Wenn man Konstruktoren fehlschlagen lassen will, dann muss man eben einen "ungültig" Status für die Objekte bauen. Ist ja keine wilde Sache. In anderen Sprachen mit Exceptions muss man sich auch um Exceptions sorgen machen, auch wenn man die nicht nutzen will@DEvent
Man kann auch in C++ explizit eine Datei schließen, wenn man den Fehlercode behandeln möchte. Die STL kennt übrigens keine Streams
-
Nexus schrieb:
Die Standardbibliothek ist ziemlich defensiv, was Exceptions anbelangt. Wenn du selbst keine Exceptions und keine Bibliotheken mit Exceptions verwendest, kann also nicht viel passieren.
Aber wehe, wenn dann irgendwann mal an dem Code, den ich Aufrufe was verändert wird, so dass er doch Exceptions wirft.
Nicht Exception-sicherer C++-Code ist unschön und problematisch wiederzuverwenden, zumal sich auch nicht so auf den ersten Blick erkennen lässt, wo er nicht exceptionsicher ist. Man sollte also vernünftigerweise schon auf Exceptionsicherheit achten, was ärgerlich ist wenn man gar keine Exceptions verwenden will.
Abgesehen davon ist Exceptionsicherheit fast gratis, wenn man RAII verwendet.
Eben nur _fast_ gratis, man muss sie trotzdem immer im Hinterkopf haben.
Gerade wenn man C-Bibliotheken verwendet bedeutet das, dass man einen Haufen ansonsten sinnloser Wrapper-Klassen schreiben muss.
Kopierkonstruktoren und Zuweisungsoperatoren musst du in den wenigsten Fällen selbst implementieren – nämlich dann, wenn du eine spezifische Kopiersemantik möchtest.
Man muss sich aber zu jeder Klasse Gedanken machen, ob die notwendig ist. Und vor allem auch dann, wenn man gar nicht vorhat, die Objekte zu kopieren, z.B. weil es sinnlos wäre. Aber jemand anders der den Code irgendwann wiederverwendet könnte es ja tun wollen.
rüdiger schrieb:
Wenn man Konstruktoren fehlschlagen lassen will, dann muss man eben einen "ungültig" Status für die Objekte bauen.
Fällt bei mir in die Kategorie "hässlicher Hack". Warum muss ich dass für jede Klasse aufs Neue selbst implementieren?
In anderen Sprachen mit Exceptions muss man sich auch um Exceptions sorgen machen, auch wenn man die nicht nutzen will
In anderen Sprachen, in denen Exceptions grundlegender Bestandteil sind und von allen Bibliotheken konsistent verwendet werden, werde ich aber Exceptions niemals nicht nutzen wollen, somit tritt das Problem nicht auf.
Das was ich an C++ so abscheulich finde ist, dass Probleme an allen möglichen Sprachfeatures damit gerechtfertig werden, dass man sie ja nicht nutzen muss wenn man sie nicht braucht/will. Aber das hat zur Folge, dass man hässlichen, schlecht wiederverwendbaren Code schreibt.
IMHO kann man in C++ nur schönen, perfekten Code schreiben, wenn man sich auf alle Sprachfeatures einlässt und (gerade wenn man viele verschiedene Bibliotheken und Frameworks verwendet) viel Zeit investiert. Wenn man produktiv sein will, muss man sich auf Kompromisse einlassen (Was deswegen bei 95% des C++-codes, der so geschrieben wird, auch gemacht wird).
Natürlich kann man das für alle Sprachen irgendwie sagen, aber IMHO ist es bei C++ am schlimmsten; schönen, wiederverwendbaren Code zu schreiben und produktiv das zu machen was man eigentlich vorhat sind meinem Eindruck nach bei C++ entgegengesetze Ziele. Eine gute Sprache sollte es erleichtern, beides gleichzeitig zu machen.
-
namespace invader schrieb:
Nicht Exception-sicherer C++-Code ist unschön und problematisch wiederzuverwenden, zumal sich auch nicht so auf den ersten Blick erkennen lässt, wo er nicht exceptionsicher ist. Man sollte also vernünftigerweise schon auf Exceptionsicherheit achten, was ärgerlich ist wenn man gar keine Exceptions verwenden will.
Das macht keinen Sinn.
Wenn du in C++ ohne exceptions arbeitest, dann brauchst du dich nicht um exceptions kuemmern, da die standard library keine wirft.
wenn man an die zukunft denkt und vermutet dass der code vielleicht doch irgendwannmal exceptions verwenden wird, tja, dann hast du das selbe problem wie in jeder sprache. aber c++ zwingt dich zu nichts. es gibt sogar systeme wo exceptions technisch garnicht unterstuetzt werden und trotzdem kann man c++ programmieren.
Gerade wenn man C-Bibliotheken verwendet bedeutet das, dass man einen Haufen ansonsten sinnloser Wrapper-Klassen schreiben muss.
nein, muss man nicht.
es macht vielleicht sinn, aber man kommt mit einer einzigen klasse aus: ein scopeguard. mehr ist nicht notwendig.Man muss sich aber zu jeder Klasse Gedanken machen, ob die notwendig ist. Und vor allem auch dann, wenn man gar nicht vorhat, die Objekte zu kopieren, z.B. weil es sinnlos wäre. Aber jemand anders der den Code irgendwann wiederverwendet könnte es ja tun wollen.
man muss beim programmieren denken? O_o
selbes problem hast du in allen sprachen.
rüdiger schrieb:
Wenn man Konstruktoren fehlschlagen lassen will, dann muss man eben einen "ungültig" Status für die Objekte bauen.
Fällt bei mir in die Kategorie "hässlicher Hack". Warum muss ich dass für jede Klasse aufs Neue selbst implementieren?
ist in allen sprachen so.
In anderen Sprachen mit Exceptions muss man sich auch um Exceptions sorgen machen, auch wenn man die nicht nutzen will
In anderen Sprachen, in denen Exceptions grundlegender Bestandteil sind und von allen Bibliotheken konsistent verwendet werden, werde ich aber Exceptions niemals nicht nutzen wollen, somit tritt das Problem nicht auf.
irrelevant. c++ bietet dir optionen und moeglichkeiten.
wenn du keine exceptions willst: bitte, c++ bietet dir die moeglichkeit
du willst exceptions nutzen: bitte, c++ bietet dir die moeglichkeitjava sagt: du musst exceptions nutzen. was in java kein problem, in c++ waere es aber eins, da c++ auch auf systemen laufen muss, wo es keine vm gibt und wo man die kosten von exceptions an die infrastruktur nicht zahlen will/kann.
Das was ich an C++ so abscheulich finde ist, dass Probleme an allen möglichen Sprachfeatures damit gerechtfertig werden, dass man sie ja nicht nutzen muss wenn man sie nicht braucht/will. Aber das hat zur Folge, dass man hässlichen, schlecht wiederverwendbaren Code schreibt.
bloedsinn.
wenn du features nicht nutzt, macht das garnichts. natuerlich ist der code ohne feature A nicht so schoen wie mit feature A. ist ja der sinn. wozu braeuchte ich sonst das feature A?
man kann aber ohne probleme grosse anwendungen in c++ schreiben ohne exceptions und templates zu nutzen. gibt massig beispiele dafuer. natuerlich waere der code mit exceptions und templates vermutlich schoener...
selbes gilt uebrigens fuer jede sprache. wenn du keine generics in java nutzen willst, dann kannst du das. aber dein code wird nicht so schoen werden wie wenn du generics nutzen wuerdest.
IMHO kann man in C++ nur schönen, perfekten Code schreiben, wenn man sich auf alle Sprachfeatures einlässt und (gerade wenn man viele verschiedene Bibliotheken und Frameworks verwendet) viel Zeit investiert. Wenn man produktiv sein will, muss man sich auf Kompromisse einlassen (Was deswegen bei 95% des C++-codes, der so geschrieben wird, auch gemacht wird).
wie in jeder sprache.
Natürlich kann man das für alle Sprachen irgendwie sagen, aber IMHO ist es bei C++ am schlimmsten; schönen, wiederverwendbaren Code zu schreiben und produktiv das zu machen was man eigentlich vorhat sind meinem Eindruck nach bei C++ entgegengesetze Ziele. Eine gute Sprache sollte es erleichtern, beides gleichzeitig zu machen.
willkommen in der realen welt.
die perfekte sprache gibt es nicht.guter code und schnell code schreiben widerspricht sich. guter code muss ueberlegt sein, egal ob in python, c++ oder cobol. c++ bietet dir alle tools die du brauchst um guten code zu schreiben. natuerlich musst du aber auch noch immer selber den code schreiben.
php ist was das betrifft zB sehr schlecht dran. code in php ist fast immer eine katastrophe, aber enorm schnell geschrieben. python ist vielleicht noch am besten dran... aber die sprache die du hier suchst, die gibt es nicht. und c++ ist von deinen zielen nicht weiter weg als java oder c#.
es gibt zB eine interessante library genannt mef (Managed Extensibility Framework) die genau zu diesem zweck existiert. code reuse ist schwer. in jeder sprache. mef erlaubt jetzt code reuse auf binary ebene in .net - eben weil guter code und realer code 2 unterschiedliche welten sind.
-
namespace invader schrieb:
Aber wehe, wenn dann irgendwann mal an dem Code, den ich Aufrufe was verändert wird, so dass er doch Exceptions wirft.
Nicht Exception-sicherer C++-Code ist unschön und problematisch wiederzuverwenden, zumal sich auch nicht so auf den ersten Blick erkennen lässt, wo er nicht exceptionsicher ist. Man sollte also vernünftigerweise schon auf Exceptionsicherheit achten, was ärgerlich ist wenn man gar keine Exceptions verwenden will.
Es kommt natürlich drauf an, welchen Level von Exceptionsicherheit man anstrebt. Will man nur die minimale Garantie - also dass alle Ressourcen wieder freigegeben werden ohne die Garantie dass der State gleich bleibt, dann macht es keinen Unterschied, ob du mit oder ohne Exceptions arbeitest. Einfach RAII befolgen. Verwendest du dabei nur das was die STL bietet, erfüllst du automatisch diese Anforderungen und musst überhaupt nicht nachdenken, das was dir der Compiler an copy-ctor, dtor und op= generiert reicht völlig aus.
Richtig ist, dass man für höhere Garantieren natürlich immer etwas Hirnschmalz reinstecken muss, zumindest für copy&swap. Aber das sind höhere Garantien. Wenn du nicht erwartest dass in deinem Code überhaupt behebbare Exceptions auftreten können, dann brauchst du darüber nicht nachdenken. Wenn ein new-fehlschlägt dann ist eh alles verloren, da bringt dir die höhere Garantie nichts.
Man muss sich aber zu jeder Klasse Gedanken machen, ob die notwendig ist. Und vor allem auch dann, wenn man gar nicht vorhat, die Objekte zu kopieren, z.B. weil es sinnlos wäre. Aber jemand anders der den Code irgendwann wiederverwendet könnte es ja tun wollen.
Der Punkt ist, dass dies für einen Großteil aller Klassen nicht notwendig ist. Der Normalfall ist nicht speziell. Und ob der Normalfall zutrifft merkt man spätestens, wnen man den dtor implementieren muss. Erst wenn dort Magie passiert, braucht man sich Gedanken drüber zu machen, ob die default-Semantik so sinnvoll ist. Aber wie bereits gesagt wurde, ist das ein Problem für alle Sprachen.
Wenn jemand kopieren will und du dir keine Gedanken drüber machtest obwohl du es hättest tun sollen, bist du eben aufgeschmissen. Wenn jemand den Code umschreibt sodass er Exceptions verwendet und du nicht drüber nachdenkst, bist du aufgeschmissen. Wenn jemand deinen Code in einem anderen Kontext verwendest und du nicht drüber nachdenkst bist du aufgeschmissen. Wenn du beim Programmieren nicht nachdenkst, bist du aufgeschmissen.Natürlich ist die Frage, ob es sich lohnt. Wenn man den Code nicht dafür auslegt dass er Exceptions vertragen soll, dann ist das okay, solange man den Kontext unter Kontrolle hat. Wenn man aber davon ausgeht, dass der Code in völlig fremder Umgebung zum Einsatz kommen wird, dann muss man natürlich Arbeit reinstecken. Aber das ist das Problem der Widerverwendbarkeit für alle Sprachen(mal von funktionalen Sprachen abgesehen. Wo kein State existiert kann nichts schief gehen).
Das was ich an C++ so abscheulich finde ist, dass Probleme an allen möglichen Sprachfeatures damit gerechtfertig werden, dass man sie ja nicht nutzen muss wenn man sie nicht braucht/will. Aber das hat zur Folge, dass man hässlichen, schlecht wiederverwendbaren Code schreibt.
C++ lässt einem die Wahl, die Features zu verwenden, natürlich muss man nicht. Du hast natürlich recht, dass bestimmte Features Probleme machen, insbesondere wenn andere Features hinzu kommen (wie exceptions und dtor). Aber das sind konzeptionelle Probleme die man nicht lösen kann. Mehrere Exceptions gleichzeitig werfen zu wollen ist nunmal in jeder Sprache problematisch. Normalerweise ist das kein Problem, außer im aufräumcode. Aber ob du in einem finallyblock das Problem hast, dass eine Exception geworfen werden kann oder in einem Destruktor macht keinen großen Unterschied.
IMHO kann man in C++ nur schönen, perfekten Code schreiben, wenn man sich auf alle Sprachfeatures einlässt und (gerade wenn man viele verschiedene Bibliotheken und Frameworks verwendet) viel Zeit investiert. Wenn man produktiv sein will, muss man sich auf Kompromisse einlassen (Was deswegen bei 95% des C++-codes, der so geschrieben wird, auch gemacht wird).
Aber auch das gilt für jedes Handwerk. Du musst dich mit deinen Werkzeugen auskennen. Wenn du das nicht tust, ist das Ergebnis minderwertig. Und wenn du im Team arbeitest und deine Teamkollegen mit den Werkzeugen nicht umgehen können, bringt es auch nicht viel, wenn du es kannst.
Wichtiger ist allerdings, dass "schöner, perfekter Code" und das Auslassen von Sprachfeatures nicht zusammen passen. Wenn ich perfekten Code ohne ein bestimmtes Feature schreiben kann, dann ist das Feature sinnlos und kann bedenkenlos vergessen werden. Wenn es mit dem Feature schöner geht, dann ist es sinnvoll und sollte verwendet werden. Der Handwerker der 1000 Werkzeuge kennt und nutzen kann, wird am Ende sicherlich auch schönere Ergebnisse haben als ein Handwerker der sich mit Hammer und Schraubenzieher begnügt. Und sicherlich hat der Handwerker mit den 1000 Werkzeugen viele Stunden länger geübt als der mit dem Miniwerkzeugkasten.Dieser Punkt wirkt auf mich so, als ob du kritisierst, dass man Zeit investieren muss, um irgendwo gut zu sein. Aber das gilt doch wirklich überall im Leben. Natürlich gibt es Sprachen, die schneller zu erlernen sind als C++, aber die haben auch einen viel kleineren Werkzeugkasten. Und es ist klar, dass man mit einem kleineren Werkzeugkasten zu Beginn schneller ans Ziel kommt, weil man eben nicht so viel Wissen muss. Trotzdem ist es manchmal besser, einen richtig großen Werkzeugkasten zu haben, der immer genau das Werkzeug enthält, das man gerade benötigt.
Dies bedeutet auch nicht, dass man mit dem großen Werkzeugkasten irgendwann schneller ist. Das behaupte ich nicht. Es ist eher so, dass man viel mehr Möglichkeiten und damit eine ganz andere Messlatte hat. Für einen kleinen Werkzeugkasten ist Perfektion einfach zu erreichen: mach was geht und wenn nichts mehr geht ist es perfekt. Nur was beim kleinen Werkzeugkasten das absolut perfekte Resultat ist, kann beim großen Werkzeugkasten wieder verbesserungswürdig sein, weil er die filigranen Kleinstwerkzeuge für die Feinarbeit enthält. Wo der eine nur 100er Schmirgelpapier hat, hat der andere das 1000er Nassschleifpapier und Feinpolitur mit denen er sich die nächsten Stunden noch vertreiben kann, bis alles glänzt und funkelt.
-
otze schrieb:
Wenn jemand kopieren will und du dir keine Gedanken drüber machtest obwohl du es hättest tun sollen, bist du eben aufgeschmissen. Wenn jemand den Code umschreibt sodass er Exceptions verwendet und du nicht drüber nachdenkst, bist du aufgeschmissen. Wenn jemand deinen Code in einem anderen Kontext verwendest und du nicht drüber nachdenkst bist du aufgeschmissen. Wenn du beim Programmieren nicht nachdenkst, bist du aufgeschmissen.
Nur dass C++ einen dazu zwingt, pausenlos über Dinge nachzudenken, die mit der Lösung des eigentlichen Problems nichts zu tun haben. Man vergeudet einen beachtlichen Teil seiner Zeit damit, alle Möglichen Dinge zu tun, die nur die Sprache (und nicht das Problem) von einem verlangt.
Das ist in anderen Sprachen nicht so. Einen finally-Block in Java (wobei ich gar nicht sagen will, dass Java nun übermäßig toll ist) schreibt man, weil das Problem es erfordert, dass bestimmte Dinge freigegeben werden, und nicht nur um es der Sprache rechtzumachen. Code zum Kopieren eines Objektes in C schreibt man nur, wenn das Problem es erfordert, dass so ein Objekt kopiert wird, und nicht um die Sprache daran zu hindern Unsinn anzustellen.
Wenn man aber davon ausgeht, dass der Code in völlig fremder Umgebung zum Einsatz kommen wird, dann muss man natürlich Arbeit reinstecken. Aber das ist das Problem der Widerverwendbarkeit für alle Sprachen
Aber gerade C++ verleitet dazu, nicht wiederverwendbaren code zu schreiben, der auch schlecht wieder "repariert" werden kann.
Natürlich ist es z.B. auch in C mühsam, auf alle Fehler richtig zu reagieren; wenn man schnell etwas fertig bekommen will schreibt man bei einem Fehler einfach eine Fehlermeldung nach stderr und beendet das Programm. Aber sowas sieht dann jeder, der über den Code guckt und kann es nachträglich sicher beheben. C++-Code im Nachhinein exceptionsicher zu machen ist mühsam und fehleranfällig.
Du musst dich mit deinen Werkzeugen auskennen. Wenn du das nicht tust, ist das Ergebnis minderwertig. Und wenn du im Team arbeitest und deine Teamkollegen mit den Werkzeugen nicht umgehen können, bringt es auch nicht viel, wenn du es kannst.
Wie gesagt ist der Grund dafür, dass in C++ minderwertige Ergebnisse erzeugt werden, vor allem der, dass es ansonsten schwierig ist produktiv zu ein. Dass sich aufgrund der hohen Komplexität von C++ ein Großteil der C++-Programmierer nicht wirklich mit C++ auskennen, kommt natürlich noch erschwerend hinzu.
Wichtiger ist allerdings, dass "schöner, perfekter Code" und das Auslassen von Sprachfeatures nicht zusammen passen. Wenn ich perfekten Code ohne ein bestimmtes Feature schreiben kann, dann ist das Feature sinnlos und kann bedenkenlos vergessen werden. Wenn es mit dem Feature schöner geht, dann ist es sinnvoll und sollte verwendet werden.
Das glaube ich nicht, und vermutlich sind der Grund für die ewige C++-Diskussion auch einfach unterschieche Auffassungen darüber, was genau "schöner, perfekter Code" ist.
Ein bestimmtes Problem (nach meinen Maßstäben) schön und elegant zu lösen erfordert nicht bestimmte, zur eleganten Lösung des Problems absolut erforderliche Sprachfeatures, sondern hängt vor allem davon ab, wie die zur Verfügung stehenden Möglichkeiten eingesetzt werden. Jedes Problem kann in (fast) jeder Sprache und mit jedem Paradigma elegant gelöst werden. Ein C-Programm für ein beliebiges, bestimmtes Problem kann genauso elegant sein wie ein C++-, Erlang- oder Haskellprogramm. Nur dass sich der Programmieraufwand dazu je nach Problem unterscheidet (und natürlich auch Laufzeit- und Speicheraufwand, Größe usw. des Erbebnisses)
Und IMHO ist der Programmieraufwand zur "eleganten" Lösung mit C++ in sehr vielen Fällen höher als in anderen Sprachen. Ohne Frage kann man in C++ auch sehr produktiv arbeiten, deshalb hat es sich so weit verbreitet, aber das was dabei in den meisten Fällen herauskommt empfinde ich nicht als schön.
Aber ich gebe ja zu, dass die Frage, was schöner, eleganter Code ist und wann man welchen schreiben sollte, subjektiv ist und auf eine Grundsatzdiskussion hinausläuft. Viele hier scheinen der Meinung zu sein, dass eine Sprache als Werkzeugkasten zu sehen ist, der idealerweise möglichst viel verschiedenen Kram enthält, von dem man sich das rauspicken kann was gerade irgendwie am besten passt. Ich will mir ja gar nicht anmaßen zu behaupten, dass deren subjektives Empfinden falsch ist (auch wenn sich viele Ärgerlichkeiten von C++ objektiv feststellen lassen). Aber nach meinem Empfinden entscheidet vor allem die Qualität und die gut durchdachte Zusammenstellung (und nicht sie Masse) der Sprachfeatures darüber, wie "gut" ein Sprache ist und wie einfach man damit eleganten Code schreiben kann, und demnach ist C++ eben eine unsaubere und relativ ekelhafte Sprache.
-
namespace invader schrieb:
Nur dass C++ einen dazu zwingt, pausenlos über Dinge nachzudenken, die mit der Lösung des eigentlichen Problems nichts zu tun haben.
Hier gabs vor einiger Zeit einen unregistrierten Troll, der in unzähligen Threads genau so gegen C++ argumentierte wie Du. Hast Du dich jetzt angemeldet?
-
namespace invader schrieb:
[...]
Nichts für ungut, aber gerade der letzte Post zeigt sehr gut, dass Du gar nicht das Grundlagenwissen hast, um objektiv eine Diskussion zum Für und Wider von C++ zu führen.
Insgesamt ist es für solche eine Diskussion hilfreich ein paar mehr Sprachen als nur C gut zu kennen. Und auch C sollte man besser als nur leidlich kennen. Durch den Vergleich von nur zwei Sprachen kann man die Defizite der jeweils anderen Sprachen gar nicht umfassend beurteilen.
-
Edit: Doppelpost... Früher gabs doch noch die Meldung, man könne nicht so schnell hintereinander einen Beitrag absenden?
-
namespace invader schrieb:
Nur dass C++ einen dazu zwingt, pausenlos über Dinge nachzudenken, die mit der Lösung des eigentlichen Problems nichts zu tun haben. Man vergeudet einen beachtlichen Teil seiner Zeit damit, alle Möglichen Dinge zu tun, die nur die Sprache (und nicht das Problem) von einem verlangt.
[...]
Aber gerade C++ verleitet dazu, nicht wiederverwendbaren code zu schreiben, der auch schlecht wieder "repariert" werden kann.
[...]
C++-Code im Nachhinein exceptionsicher zu machen ist mühsam und fehleranfällig.
[...]
Wie gesagt ist der Grund dafür, dass in C++ minderwertige Ergebnisse erzeugt werden, vor allem der, dass es ansonsten schwierig ist produktiv zu ein. Dass sich aufgrund der hohen Komplexität von C++ ein Großteil der C++-Programmierer nicht wirklich mit C++ auskennen, kommt natürlich noch erschwerend hinzu.
[...]
Und IMHO ist der Programmieraufwand zur "eleganten" Lösung mit C++ in sehr vielen Fällen höher als in anderen Sprachen. Ohne Frage kann man in C++ auch sehr produktiv arbeiten, deshalb hat es sich so weit verbreitet, aber das was dabei in den meisten Fällen herauskommt empfinde ich nicht als schön.Jetzt fallen dir wohl keine Argumente mehr ein und stattdessen bringst du allgemeingültige, austauschbare und unbegründete Behauptungen?
Wir haben zu jedem konkreten Kritikpunkt Stellung genommen. Irgendwann ist halt fertig, und dann muss die Diskussion auch ohne Argumente weitergehen, nicht wahr?
-
namespace invader schrieb:
Nur dass C++ einen dazu zwingt, pausenlos über Dinge nachzudenken, die mit der Lösung des eigentlichen Problems nichts zu tun haben. Man vergeudet einen beachtlichen Teil seiner Zeit damit, alle Möglichen Dinge zu tun, die nur die Sprache (und nicht das Problem) von einem verlangt.
Man muss nachdenken, OMG.
Das ist kein Argument. In Java muss ich dauernd finallys schreiben obwohl die mit meinem Problem nichts zu tun haben... Dieser Vorgang nennt sich nunmal "programmieren".Das ist in anderen Sprachen nicht so. Einen finally-Block in Java (wobei ich gar nicht sagen will, dass Java nun übermäßig toll ist) schreibt man, weil das Problem es erfordert, dass bestimmte Dinge freigegeben werden, und nicht nur um es der Sprache rechtzumachen.
Nein. Ein finally schreibst du, weil die Objekte dumm sind und sich nicht selber aufräumen können. In C++ schreibst du keinen aufräum code, weil du das nicht musst.
Warum schreibt man in Java wohl dauernd:
if(o!=null) { try { o.close(); } catch(Exception e) {} }
weil die sprache es eben erfordert. das objekt könnte sich ja ruhig auch selber aufräumen, aber die sprache erfordert manuelles löschen aller resourcen.
aber java ist nicht toll? welche sprache dann?
Code zum Kopieren eines Objektes in C schreibt man nur, wenn das Problem es erfordert, dass so ein Objekt kopiert wird, und nicht um die Sprache daran zu hindern Unsinn anzustellen.
in c++ schreibt man den code garnicht, weil er automatisch generiert wird.
und objekte in C kopieren funktioniert ja auch automatisch. ist dann halt immer eine flache kopie.
in java muss man auch ein clone schreiben wenn es notwendig ist... c++ ist hier nicht viel anders. wenn du nicht kopieren willst, einfach boost::nocopy und gut ist. so einfach ist das in C und Java zB nicht...
Aber gerade C++ verleitet dazu, nicht wiederverwendbaren code zu schreiben, der auch schlecht wieder "repariert" werden kann.
das ist deine meinung. hast du dafür auch fakten?
Natürlich ist es z.B. auch in C mühsam, auf alle Fehler richtig zu reagieren; wenn man schnell etwas fertig bekommen will schreibt man bei einem Fehler einfach eine Fehlermeldung nach stderr und beendet das Programm. Aber sowas sieht dann jeder, der über den Code guckt und kann es nachträglich sicher beheben. C++-Code im Nachhinein exceptionsicher zu machen ist mühsam und fehleranfällig.
c++ code ist von hausaus exception sicher, es sei denn du hast einen fehler gemacht.
fehlerbehandlung in c ist um viele klassen schwerer als in c++. alleine das aufräumen bei einem fehler...*brr*.
schreib mal bitte mein Java Beispiel mit dem 2 Dateien kopieren in C mit korrekter Fehlerbehandlung. Mal davon abgesehen dass du nie printf auf fehler überprüfen wirst (und somit nie die sicherheit eines c++ oder java codes haben kannst) ist das aufräumen in C eine totale katastrophe.
Wie gesagt ist der Grund dafür, dass in C++ minderwertige Ergebnisse erzeugt werden, vor allem der, dass es ansonsten schwierig ist produktiv zu ein. Dass sich aufgrund der hohen Komplexität von C++ ein Großteil der C++-Programmierer nicht wirklich mit C++ auskennen, kommt natürlich noch erschwerend hinzu.
wo hast du minderwertige ergebnisse?
schau dir irgendeine Sprache an, egal welche.Alle deine "argumente" kann ich problemlos auf diese Sprache anwenden. oder zeig mir eine sprache die nicht komplex ist aber dennoch alle tools so anbietet dass man immer gut damit arbeiten kann.
diese sprache gibt es nicht. in c ist zB das aufräumen eine absolute katastrophe.
Ein bestimmtes Problem (nach meinen Maßstäben) schön und elegant zu lösen erfordert nicht bestimmte, zur eleganten Lösung des Problems absolut erforderliche Sprachfeatures, sondern hängt vor allem davon ab, wie die zur Verfügung stehenden Möglichkeiten eingesetzt werden.
so kann man sich alles schön reden.
Jedes Problem kann in (fast) jeder Sprache und mit jedem Paradigma elegant gelöst werden. Ein C-Programm für ein beliebiges, bestimmtes Problem kann genauso elegant sein wie ein C++-, Erlang- oder Haskellprogramm. Nur dass sich der Programmieraufwand dazu je nach Problem unterscheidet (und natürlich auch Laufzeit- und Speicheraufwand, Größe usw. des Erbebnisses)
kleines beispiel: typelist
in C und in C++
oder ein mathe-ausdrucks parser in Java versus in OCaml.
Gewisse Features erlauben deutlich schöneren Code. Egal wie du schöner definierst: kürzer, eleganter, schneller,... Pattern Matching in OCaml ist für gewisse Situationen einfach in jeder hinsicht besser als alles was Java bietet.
Und IMHO ist der Programmieraufwand zur "eleganten" Lösung mit C++ in sehr vielen Fällen höher als in anderen Sprachen. Ohne Frage kann man in C++ auch sehr produktiv arbeiten, deshalb hat es sich so weit verbreitet, aber das was dabei in den meisten Fällen herauskommt empfinde ich nicht als schön.
wie in jeder sprache.
Aber nach meinem Empfinden entscheidet vor allem die Qualität und die gut durchdachte Zusammenstellung (und nicht sie Masse) der Sprachfeatures darüber, wie "gut" ein Sprache ist und wie einfach man damit eleganten Code schreiben kann, und demnach ist C++ eben eine unsaubere und relativ ekelhafte Sprache.
C++ bietet viele Features die du woanders garnicht hast. wie willst du das vergleichen? schau dir zB von gmp das C und das C++ interface an. gmp ist häßlich, aber die c++ variante ist um soviele dimensionen besser zu benutzen als die C variante - und das obwohl der c++ code eher schlecht ist.
der standard in c++ ist halt sehr hoch - weil man eben so elegante sachen machen kann. wenn du aber 0815 c++ code mit 0815 java code vergleichst, nehem sie sich nichts.
-
namespace invader schrieb:
[...] Man verschwendet also Zeit, nur um sich um Sprachfeatures zu kümmern, die man gar nicht nutzen will. Im Prinzip das selbe wie die Kopierkonstruktoren und Zuweisungsoperatoren, für die man ständig Zeit opfert obwohl man sie eigentlich gar nicht braucht. [...]
Schlechtes Beispiel. Schreibst Du ständig Kopierkonstruktoren und Zuweisungsoperatoren für eigene Klassen? Ich nicht. Das macht man in der Regel nur für wenige "kleine Bausteine" wie zB std::string oder std::vector, welche in den zwei Fällen praktischerweise Teile der Standardbibliothek sind. Wenn Du eigene Klassen aus solchen Bausteinen zusammensetzt, kannst Du das mit dem Kopieren und Zuweisen komplett dem Compiler überlassen. Das ist überhaupt eine der wichtigsten Lektionen, die man bei C++ gelernt haben sollte und die bei Dir scheinbar bisher nicht angekommen ist.
-
Shade Of Mine schrieb:
Man muss nachdenken, OMG.
Das ist kein Argument. In Java muss ich dauernd finallys schreiben obwohl die mit meinem Problem nichts zu tun haben... Dieser Vorgang nennt sich nunmal "programmieren".Es ist schon ein gewaltiger Unterschied, ob ich über das eigentliche Problem oder die Sprache nachdenken muss. Das was du in finally-Blöcke schreibst, gehört ja zu deinem Problem. Dateien müssen nun mal wieder geschlossen werden (dass man dazu in Java optisch unschön geschachtelte finally-Blöcke braucht, ist eben die Eigenheit von Java, aber das ist ein anderes Thema). Wenn ich aber sinnlose Kopierkonstruktoren schreiben muss (oder zumindest private deklarieren), hat das mit meinem Problem nichts zu tun.
aber java ist nicht toll? welche sprache dann?
Na C zum Beispiel
in c++ schreibt man den code garnicht, weil er automatisch generiert wird.
...und zwar falsch, außer für einfache Klassen.
und objekte in C kopieren funktioniert ja auch automatisch. ist dann halt immer eine flache kopie.
Bei C ist das nicht weiter problematisch, weil C nicht so tut als wäre es eine High-Level-Sprache. Bei C hat man den Überblick darüber, wo Objekte kopiert werden und wo man explizit eine tiefe Kopie machen muss. Der Sinn von C++ ist ja gerade, dass solche Dinge versteckt werden, was leider nicht klappt.
Aber dieser Vergleich des impliziten Kopierens in C und C++ macht schön deutlich, wie genau das selbe Feature in C sinnvoll ist, aber in C++ störend. Das ist ja genau mein Punkt: Mehr Features führen nicht automatisch zu einer besseren Sprache; es kommt auf die Zusammenstellung der Features an.
in java muss man auch ein clone schreiben wenn es notwendig ist...
Eben: _Wenn_ es notwendig ist, also wenn mein Problem es erfordert.
wenn du nicht kopieren willst, einfach boost::nocopy und gut ist.
Immer diese blöden Workarounds bei C++...
Aber gerade C++ verleitet dazu, nicht wiederverwendbaren code zu schreiben, der auch schlecht wieder "repariert" werden kann.
das ist deine meinung. hast du dafür auch fakten?
Hab ich doch erklärt (Verzicht auf Exceptionsicherheit und Verzicht auf Kopierkonstruktoren und Zuweisungsop. obwohl "notwendig").
c++ code ist von hausaus exception sicher, es sei denn du hast einen fehler gemacht.
Unsinn. C++-Code ist nur dann automatisch exceptionsicher, wenn man (und alle Frameworks und Bibliotheken, die man verwendet) sich voll auf das RAII-Paradigma einlässt. Aber bei vielen Frameworks wurde gar nicht daran gedacht, zumal Exceptions ja erst nachträglich auf C++ draufgepappt wurden. Und C-Bibliotheken natürlich sowieso nicht (und das, obwohl doch die Kompatibilität zu C der vielgepriesene Vorteil von C++ ist
)
schreib mal bitte mein Java Beispiel mit dem 2 Dateien kopieren in C mit korrekter Fehlerbehandlung.
int cf(const char *a, const char *b) { int err = 0; FILE *src = fopen(a, "rb"); FILE *trg = fopen(b, "wb"); if (!src || !trg) { err = -1; goto end; } if (copy(trg, src) < 0) err = -2; end: if (src) fclose(src); if (trg) fclose(trg); return err; }
Und was soll daran jetzt so schlimm sein? (Und wenn man sich für fclose-Fehler interessiert, erhöht das nicht mal die Zeilenanzahl, während man in C++ ein Problem hat, wenn im Destruktor was schief geht).
Mal davon abgesehen dass du nie printf auf fehler überprüfen wirst
Kann ich aber, wenn mein Problem es erfordert, dass ich weiß ob dort ein Fehler aufgetreten ist.
Alle deine "argumente" kann ich problemlos auf diese Sprache anwenden. oder zeig mir eine sprache die nicht komplex ist aber dennoch alle tools so anbietet dass man immer gut damit arbeiten kann.
Du hast ja nicht verstanden, was ich gesagt habe. Was ich an C++ kritisiere ist nicht, dass bestimmte Dinge etwas mühsam zu machen sind (das gibt es in jeder Sprache), sondern die "Werkzeugkasten"-Philosophie von C++, die zur Folge hat dass man mehr mit der Sprache und ihren ganzen Features zu tun hat als mit dem eigentlichen Problem.
kleines beispiel: typelist
...schönes Feature für Leute, die lieber über ihre Programmiersprache nachdenken als über die Probleme, die sie eigentlich damit lösen wollen...
Gewisse Features erlauben deutlich schöneren Code. Egal wie du schöner definierst: kürzer, eleganter, schneller,... Pattern Matching in OCaml ist für gewisse Situationen einfach in jeder hinsicht besser als alles was Java bietet.
"Schönen, eleganten" Code habe ich definiert als "die vorhandenen Möglichkeiten am besten ausnutzend", und mit dieser Definition ist deine Behauptung natürlich Unsinn. Dass bestimmte Sprachen für bestimmte Probleme besser geeignet sind und dann kürzeren, verständlicheren Code erlauben, ist ja keine Frage.
schau dir zB von gmp das C und das C++ interface an. gmp ist häßlich, aber die c++ variante ist um soviele dimensionen besser zu benutzen als die C variante - und das obwohl der c++ code eher schlecht ist.
Kenn ich nicht, aber auf den ersten Blick scheint es doch eine ordentliche C-Bibliothek zu sein.
Natürlich bietet sich für so etwas Operatorüberladung an, und wenn man sie hat sieht das Programm damit "natürlicher" aus, aber letztendlich ist der Unterschied nur syntaktisch. Genauso wie ein Parser, den man in einer funktionalen Sprache mit nur einem Bruchteil der Zeilen schreiben kann im Vergleich zu z.B. Java, auch nichts anderes macht.
(das restliche Rumgetroll-Hintergrundrauschen in dem Thread ignoriere ich mal weiterhin)
-
namespace invader schrieb:
Es ist schon ein gewaltiger Unterschied, ob ich über das eigentliche Problem oder die Sprache nachdenken muss. Das was du in finally-Blöcke schreibst, gehört ja zu deinem Problem. Dateien müssen nun mal wieder geschlossen werden (dass man dazu in Java optisch unschön geschachtelte finally-Blöcke braucht, ist eben die Eigenheit von Java, aber das ist ein anderes Thema). Wenn ich aber sinnlose Kopierkonstruktoren schreiben muss (oder zumindest private deklarieren), hat das mit meinem Problem nichts zu tun.
Doch. Es is Teil des Problems zu definieren, ob ein Objekt kopierbar sein soll oder nicht, weil dies in Zukunft bestimmt wie mit dem Objekt umgegangen werden kann. Dieses Problem befindet sich aber auf Softwaretechnischer Ebene, nicht auf Programmebene.
So wie ich dich verstehe bist du für ein "opt-in" bei der Kopiersemantik, während C++ ein "opt-out" verwendet. Es ist eine Entscheidung im Sprachdesign, was verwendet wird. Für Java ist ein "opt-out" nicht sinnvoll, da aufgrund der Semantik der Referenzen in Java nicht geschlossen werden kann, wie ein Objekt überhaupt kopiert werden könnte. Dies ist in C++ wesentlich einfacher, weil externe Referenzen einen Sonderfall darstellen. In C++ ist ein "opt-in" hingegen nicht sinnvoll, weil C++ hauptsächlich auf der value-Semantik aufbaut. Und zu der gehört nunmal, dass Objekte kopiert werden können.
...und zwar falsch, außer für einfache Klassen.
Einfache Klassen sind aber der Normalfall. Die meisten Klassen verwenden einfachste Objektkomposition sowie Vererbunghierarchien. Und von den wenigen Stellen in denen Zeiger verwendet werden sind die allermeisten wieder Zeiger auf externe Objekte, weil die internen Zeiger durch die RAII-basierten Container der STL zu genüge abgedeckt werden. Also reicht auch hier meistens wenn die Addresse kopiert wird. Dass man eine DeepCopy schreiben muss ist somit unglaublich selten. Hier gilt als Faustregel: schreibst du einen dtor, dann musst du den copy-ctor mit implementieren. Und das ist wirklich nichts was man mehrmals täglich machen muss. Wesentlich öfter möchte man einfache Datenkollektionen kopieren, und für DIE jeweils einen copy-ctor zu schreiben ist übelste Frohnarbeit.
Nebenbei fällt mir neben dem Singleton kaum eine Situation ein, bei der ich sowas wie boost::nocopy bräuchte.
Unsinn. C++-Code ist nur dann automatisch exceptionsicher, wenn man (und alle Frameworks und Bibliotheken, die man verwendet) sich voll auf das RAII-Paradigma einlässt. Aber bei vielen Frameworks wurde gar nicht daran gedacht, zumal Exceptions ja erst nachträglich auf C++ draufgepappt wurden.
Dass schlecht designte und veraltete Bibliotheken ne Menge am Sprachdesign zerschießen können passiert dir in jeder Sprache. Das ist ein Nullargument. Dass man C-Code anders handlen muss als C++-Code ist offensichtlich. Wenn man will, kann man sich Wrapperklassen schreiben, meistens reichts aber, wenn man in diesen Fällen einfach sinnvoll den dtor und copy-ctor der verwendenden Klassen implementiert. Auch C++ Programmierer können pragmatisch sein
-
namespace invader schrieb:
Es ist schon ein gewaltiger Unterschied, ob ich über das eigentliche Problem oder die Sprache nachdenken muss. Das was du in finally-Blöcke schreibst, gehört ja zu deinem Problem.
Interessanter Punkt.
Es gehört nur in Java zu meinem Problem, in C++ nicht. Weil Java mich dazu zwingt es zu meinem Problem zu machen. In anderen Sprachen ist das finally nicht mein Problem.
Dateien müssen nun mal wieder geschlossen werden (dass man dazu in Java optisch unschön geschachtelte finally-Blöcke braucht, ist eben die Eigenheit von Java, aber das ist ein anderes Thema). Wenn ich aber sinnlose Kopierkonstruktoren schreiben muss (oder zumindest private deklarieren), hat das mit meinem Problem nichts zu tun.
in python und c++ ist der komplette code unnötig. dort ist es nicht mein problem
in c++ schreibt man den code garnicht, weil er automatisch generiert wird.
...und zwar falsch, außer für einfache Klassen.
dann sind deine klassen falsch.
wenn du nur korrekte klassen als member hast, dann ist der standard copy ctor einwandfrei.
und objekte in C kopieren funktioniert ja auch automatisch. ist dann halt immer eine flache kopie.
Bei C ist das nicht weiter problematisch, weil C nicht so tut als wäre es eine High-Level-Sprache. Bei C hat man den Überblick darüber, wo Objekte kopiert werden und wo man explizit eine tiefe Kopie machen muss. Der Sinn von C++ ist ja gerade, dass solche Dinge versteckt werden, was leider nicht klappt.
und deshalb sind automatische falche kopien ok? aber in c++ sind automatische tiefe kopien nicht ok?
Aber dieser Vergleich des impliziten Kopierens in C und C++ macht schön deutlich, wie genau das selbe Feature in C sinnvoll ist, aber in C++ störend. Das ist ja genau mein Punkt: Mehr Features führen nicht automatisch zu einer besseren Sprache; es kommt auf die Zusammenstellung der Features an.
ich würde sagen, dass du eine doppelmoral an den tag legst. so kann man nicht diskutieren.
in java muss man auch ein clone schreiben wenn es notwendig ist...
Eben: _Wenn_ es notwendig ist, also wenn mein Problem es erfordert.
selbes in c++. ich glaube aber dein c++ ist nicht ok. denn wenn du dauernd copy ctors implementieren musst, dann passt da was nicht.
wenn du nicht kopieren willst, einfach boost::nocopy und gut ist.
Immer diese blöden Workarounds bei C++...
wie genau verbietest du eine kopie in C?
GARNICHT.
wow. ist ja viel besser als eine zeile code.c++ code ist von hausaus exception sicher, es sei denn du hast einen fehler gemacht.
Unsinn. C++-Code ist nur dann automatisch exceptionsicher, wenn man (und alle Frameworks und Bibliotheken, die man verwendet) sich voll auf das RAII-Paradigma einlässt. Aber bei vielen Frameworks wurde gar nicht daran gedacht, zumal Exceptions ja erst nachträglich auf C++ draufgepappt wurden. Und C-Bibliotheken natürlich sowieso nicht (und das, obwohl doch die Kompatibilität zu C der vielgepriesene Vorteil von C++ ist
)
ich habe damit null probleme. weil libraries die exceptions verwenden sowieso exception sicher sind und libraries die keine exceptions verwenden auch keine gefahr laufen exceptions abzubekommen.
und c libraries sind leicht wrapbar, dank scopeguards.
aber klar, schlechte libraries sind immer wieder ein problem. aber das ist ein problem das JEDE SPRACHE hat.
int cf(const char *a, const char *b) { int err = 0; FILE *src = fopen(a, "rb"); FILE *trg = fopen(b, "wb"); if (!src || !trg) { err = -1; goto end; } if (copy(trg, src) < 0) err = -2; end: if (src) fclose(src); if (trg) fclose(trg); return err; }
und jetzt nochmal das ganze in c++
ifstream src(a); ofstream trg(b); copy(a,b);
aber gut, du hast dich wenigstens getraut die gotos zu machen, das ist immerhin schon etwas. was du natürlich vergessen hast, war ordentliches error reporting:
welche datei ist fehlgeschlagen (welcher datei name war es denn?), hat das fclose funktioniert? und du öffnest unnötigerweise die 2. datei wenn die erste nicht aufgeht.
c++ bietet alle diese von mir genannten features von hausaus.
Und was soll daran jetzt so schlimm sein? (Und wenn man sich für fclose-Fehler interessiert, erhöht das nicht mal die Zeilenanzahl, während man in C++ ein Problem hat, wenn im Destruktor was schief geht).
die probleme habe ich oben beschrieben und das dtor "problem" haben wir schon so oft besprochen... es ist als rede man gegen eine wand...
Mal davon abgesehen dass du nie printf auf fehler überprüfen wirst
Kann ich aber, wenn mein Problem es erfordert, dass ich weiß ob dort ein Fehler aufgetreten ist.
doppel moral
mal ist es gut, mal ist es schlecht dass man etwas ignorieren kann.
bei exceptions findest du es schlecht dass man exception sicherheit ignorieren kann, bei error codes ist es wieder ein vorteil...Du hast ja nicht verstanden, was ich gesagt habe. Was ich an C++ kritisiere ist nicht, dass bestimmte Dinge etwas mühsam zu machen sind (das gibt es in jeder Sprache), sondern die "Werkzeugkasten"-Philosophie von C++, die zur Folge hat dass man mehr mit der Sprache und ihren ganzen Features zu tun hat als mit dem eigentlichen Problem.
du kannst keine philosophie kritisieren die du nicht verstehst, das macht keinen sinn.
kleines beispiel: typelist
...schönes Feature für Leute, die lieber über ihre Programmiersprache nachdenken als über die Probleme, die sie eigentlich damit lösen wollen...
die alternative sind void*. das ist auch nicht wirklich das gelbe vom ei.
aber als man in java damals nur void* in collections gesteckt hat, da war das cool. dann gabs generics und plötzlich sind void* in java auch wieder schlecht.
lustig, nicht wahr? solche features sind nicht zwingend erforderlich, erleichtern das programmieren aber enorm. selbes mit typelists, weil void* einfach furchtbar ist.
Dass bestimmte Sprachen für bestimmte Probleme besser geeignet sind und dann kürzeren, verständlicheren Code erlauben, ist ja keine Frage.
und wieder doppel moral.
bestimmte sprachen sind in bestimmten situationen besser, aber die tools um besser zu sein braucht man ja nicht. wie zB typelists unnötig sind weil man ja void* hat.Natürlich bietet sich für so etwas Operatorüberladung an, und wenn man sie hat sieht das Programm damit "natürlicher" aus, aber letztendlich ist der Unterschied nur syntaktisch. Genauso wie ein Parser, den man in einer funktionalen Sprache mit nur einem Bruchteil der Zeilen schreiben kann im Vergleich zu z.B. Java, auch nichts anderes macht.
wartbarkeit, produktivität und lesbar sind also keine relevanten punkte?
das ist diese doppel moral.
du magst c++ nicht. bitte. das ist ja kein problem. ich mag zB ruby nicht so. aber deine argumente sind haarsträubend. weil du auf der einen seite die produktivität von c++ code kritisierst und auf der anderenseite dann sagst dass c++ hier nur syntax sugar bietet. aber was ist syntax sugar wenn nicht produktivität?c++ codes sind den bruchteil eines c codes lang.
das datei beispiel mal korrekt:int err=0; FILE* src=NULL; FILE* trg=NULL; if(!(src=fopen(a,"r")) { err = -1; goto end; } if(!(trg=fopen(b,"r")) { err = -2; goto end; } if(!copy(src, trg)) { err = -3; goto end; } end: if(src) { fclose(src); } if(trg) { fclose(trg); } if(err) { set_error(err); } /*errno setzen*/ return err;
nochmal dazu den c++ code:
ifstream src(a); ofstream trg(b); copy(a,b);
und jetzt denk über produktivität nach.
c++ verhindert dass man über eine menge sachen nachdenken muss, wie eben zB aufräumen, error codes oder generell fehler behandlung.im gegenzug muss man eben an exception sicherheit denken. in c und java verbringt man eine menge zeit mit aufräum arbeiten. lustig wird es nämlich wenn resourcen voneinander abhängen zB wenn man einen buffer für eine datei setzt, aber die datei nicht aufgeht. dann muss man an viele sachen denken - das ist halt programmieren.
c++ nimmt auf diesem gebiet enorm viel arbeit ab. sowas wie aufräumen gibt es in c++ nicht. dafür muss man an anderer stelle eben mehr denken. aber nicht so triviale sachen wie ob da ein copyctor her muss oder nicht. das passiert automatisch. ich habe noch nie nachgedacht ob ich einen copyctor brauche oder nicht. genausowenig wie ich nachdenke ob ich in java oder c einen copyctor brauche.
du musst dich wohl mehr mit unterschiedlichen sprachen befassen. wenn du c zB für eine tolle sprache hältst und von produktivität redest, dann passt da etwas nicht. C hat seine stärken, aber sicher nicht in der produktivität. in python oder c++ oder sogar java hat man mit viel weniger code viel mehr.
deshalb eine kleine frage: in welchen sprachen hast du denn schon programme geschrieben?
-
namespace invader schrieb:
in c++ schreibt man den code garnicht, weil er automatisch generiert wird.
...und zwar falsch, außer für einfache Klassen.
Wie schon angetönt müssen Kopierkonstruktoren etc. für ein paar wenige Verwaltungsklassen mit spezieller Kopiersemantik geschrieben werden. Der Rest (und das ist der Grossteil) funktioniert.
namespace invader schrieb:
und objekte in C kopieren funktioniert ja auch automatisch. ist dann halt immer eine flache kopie.
Bei C ist das nicht weiter problematisch
Doch, du musst nämlich ständig dran denken und Fälle unterscheiden. Manchmal reicht flache Kopie, manchmal nicht. Ausserdem gibt es keine standardisierte tiefe Kopierfunktion, bei jeder Bibliothek sehen Kopien etwas anders aus. Bei C++ hingegen hast du mit
Typ kopie = original;
jedes Objekt kopieren (sofern eine Kopie sinnvoll ist).namespace invader schrieb:
Der Sinn von C++ ist ja gerade, dass solche Dinge versteckt werden, was leider nicht klappt.
Was klappt nicht? Kopierkonstruktoren jedenfalls schon, wie erwähnt.
namespace invader schrieb:
in java muss man auch ein clone schreiben wenn es notwendig ist...
Eben: _Wenn_ es notwendig ist, also wenn mein Problem es erfordert.
Und wo ist jetzt der Nachteil, wenn einem diese Arbeit von der Programmiersprache abgenommen wird?
namespace invader schrieb:
wenn du nicht kopieren willst, einfach boost::nocopy und gut ist.
Immer diese blöden Workarounds bei C++...
Immer diese Nicht-C++ler, die alle Konzepte, welche nicht Sprachmittel sind, als Workarounds darstellen...
namespace invader schrieb:
Hab ich doch erklärt (Verzicht auf Exceptionsicherheit und Verzicht auf Kopierkonstruktoren und Zuweisungsop. obwohl "notwendig").
Es wurden aber auch entsprechende Gegenargumente gebracht.
namespace invader schrieb:
Unsinn. C++-Code ist nur dann automatisch exceptionsicher, wenn man (und alle Frameworks und Bibliotheken, die man verwendet) sich voll auf das RAII-Paradigma einlässt.
Ja, und welcher C++-Programmierer, der sich auskennt, tut das nicht?
namespace invader schrieb:
Aber bei vielen Frameworks wurde gar nicht daran gedacht, zumal Exceptions ja erst nachträglich auf C++ draufgepappt wurden.
Exceptions sind seit dem ersten Standard in C++.
namespace invader schrieb:
Und C-Bibliotheken natürlich sowieso nicht
Auch hier wurde schon ein Gegenargument gebracht. Viel mehr als eine ScopeGuard-Klasse brauchst du nicht, um C-Code exceptionsicher zu machen. Dank Templates geht das sogar sehr generisch.
namespace invader schrieb:
Mal davon abgesehen dass du nie printf auf fehler überprüfen wirst
Kann ich aber, wenn mein Problem es erfordert, dass ich weiß ob dort ein Fehler aufgetreten ist.
Tust du bestimmt nicht an allen Orten, wo Fehler auftreten können. Das würde Code durch die Abfragen und das Hochreichen viel zu hässlich machen. In C++ erfährt man von solchen Fehlern, ohne im Anwendungscode etwas zu tun.
namespace invader schrieb:
kleines beispiel: typelist
...schönes Feature für Leute, die lieber über ihre Programmiersprache nachdenken als über die Probleme, die sie eigentlich damit lösen wollen...
Du hast den Einsatzzweck von Typlisten nicht verstanden.
-
namespace invader schrieb:
aber java ist nicht toll? welche sprache dann?
Na C zum Beispiel
C ganz sicher nicht. Fehlerbehandlung ist einfach willkürlich. Dies führt sogar zu Sicherheitslücken! Wiederverwendbarkeit ist äußerst gering. Selbst in ein und dem selben Projekt ist man ständig damit beschäftigt, die selben Datenstrukturen neu zu implementieren, allein weil es keine Templates gibt. Jede Überprüfung muss explizit hingeschrieben werden, da sie nicht implizit versteckt werden können (zB Bereichsüberprüfungen). Es gibt keine Funktoren, sondern nur teure Funktionspointer, Namensbereich-Kollisionen etc. C ist wirklich nicht das gelbe vom Ei.
-
rüdiger schrieb:
namespace invader schrieb:
aber java ist nicht toll? welche sprache dann?
Na C zum Beispiel
C ganz sicher nicht.
Dieser ganze high-level Schnick-Schnack ist doch pure Zeitverschwendung. Selbst C geht da schon zu weit. Wir sollten uns wieder auf einfachere Dinge konzentrieren. Turingmaschinen! Und lasst uns auch all das ignorieren, was die C++ Spezis von sich geben. Ist doch alles nur erlogen und erstunken. Da ist eine riesige Verschwörung im Gange. Selbst Herr Stroustrup hat es einmal zugegeben.
rüdiger schrieb:
[...] Selbst in ein und dem selben Projekt ist man ständig damit beschäftigt, die selben Datenstrukturen neu zu implementieren, allein weil es keine Templates gibt [...]
Du bist viel zu verwöhnt von dem high-level Schnick-Schnack, der Typsicherheit, Generizität, etc. Der gemeine C-Programmierer hat eine ganz andere Ekelgrenze. Die scheuen nicht vor Zeiger-Arithmetik-Hacks und void*-Orgien zurück. Das ist echte Generizität. Wo Programmierer noch Programmierer sind und keine Weicheier. Ganz "ohne Sicherheitsgurt" und ohne Compilerunterstützung geht das auch -- man muss nur cool genug dafür sein -- oder eben keine Ahnung von C++ haben ... :p
-
krümelkacker schrieb:
[...] Selbst Herr Stroustrup hat es einmal zugegeben. [...]
Upps! Das war der falsche Link. Der hier ist richtig.
-
krümelkacker schrieb:
Die scheuen nicht vor Zeiger-Arithmetik-Hacks und void*-Orgien zurück. Das ist echte Generizität.
Absolut und da sagt noch jemand angesichts derartiger Konstrukte:
typedef unsigned (*PROCESS)(void*, unsigned); unsigned CalcNextStep(void* setOfFormulas, unsigned curTime){ } unsigned CursorMove(void* cursorData, unsigned curTime){ } unsigned UpdateTable(void* tableTarget, unsigned curTime){ } PROCESS TodoList[8] = {CalcNextStep, CursorMove, UpdateTable};
in C gäbe es weder Funktoren noch Generizität. Einige Aufgaben sind überhaupt nur mit C-Mitteln lösbar:
Mit der oben skizzierten Schablone lassen sich z.B. recht elegant flexible TODO-Listen/Stacks für synchron und automatisiert ablaufende Prozesse (von beliebiger Lebensdauer) basteln, von deren Terminierung (die nach n-maliger Zuteilung eines Scheibchens Rechenzeit eintritt) auch die eventuelle Aufnahme(Löschung) weiterer Prozesse in die (aus der) TODO-Liste abhängen kann),
ein Beispiel für eine Problemstellung, die jetzt vielleicht nicht alltäglich ist, aber die mit C++ Mitteln vermutlich überhaupt nicht lösbar wäre. D.h. solange man nicht gewillt ist, als C++ Programmierer auf C-Funktoren zurückzugreifen.