Hallo, ich schreibe meine Programme auf dem AVR (hauptsächliche mega328P, mega644 und tiny841) hauptsächlich in avr-gcc. Nun stellt sich mir die Frage, macht C++ inzwischen mehr Sinn als vor ein paar Jahren? Ein Punkt, der mich in C etwas stört ist, dass man keine Funktionen überlagern kann. Die meisten Funktionen bestehen aus einer großen Kombination an kleinen Funktionen. Um auch noch lesbar etwas zu schaffen, werden diese dann unnötig lang.
Meiner Meinung nach ja. Lasst die Spiele beginnen, ich geh schon mal Popcorn holen.
Hermann U schrieb: > hauptsächliche mega328P, > mega644 und tiny841 Schau dir doch nur mal an was mit Arduino möglich ist und was nicht. So, jetzt werden hier gleich sehr viele Leute sehr böse... Ich mag es auch absolut nicht und bin absolut froh wenn alles sauber in C geschrieben ist. Dennoch funktionieren tut es. -D
Wenn du auf die C++-Features verzichtest, die nicht ordentlich funktionieren (oder die massiv Code erzeugen), warum nicht? Ein paar Klassen, überlagerte Funktionen und so weiter kannst du problemlos nutzen.
Wieder die gleiche alte Diskussion. Das bisherige Fazit war immer: C++ kann durchaus Sinn machen da es an manchen Stellen gegenüber C erhebliche Vereinfachungen bietet. Es ist einfach eleganter zu benutzen. Man muss und sollte allerdings nicht den ganzen Funktionsumfang von C++ auf keinen Mikrocontrollern ausschöpfen.
... und Datenkapselung und einen typesicheren enum und ...
Da ich Arduino Jünger bin darf ich die Features aufregungslos genießen. Aber wenn man sich solche Brocken, wie den Linux Kernel anschaut, dann ist recht klar, dass es auch ohne das ++ geht.
Warte nur, bis Moby hier aufschlägt. Der weiß wirklich Bescheid, was man so alles auf einen Atmel braucht. ;)
Ich verwende auch immer c++ wenn ich AVRs Programmiere, auch wenn ich nicht mit Objekten rumhantiere. Alleine wegen Namespace und enum struct. Wenn man nur Features benutzt die der Compiler auflöst und kein Overhead zur Laufzeit verursacht spricht nichts gegen c++. Bei Verwendung von Klassen bin ich immer sparsam, man sollte Kosten und Nutzen immer abwägen. Sobald wegen virtuellen Methoden eine Lookuptabele angelegt werden muss, wird dadurch der Programmcode größer und man hat Nachteile im Laufzeitverhalten.
nicht“Gast“ schrieb: > Warte nur, bis Moby hier aufschlägt. Der weiß wirklich Bescheid, was man > so alles auf einen Atmel braucht. ;) Dann werde ich sofort von Jörg W.'s Angebot Gebrauch machen, ihn rausbekamen zu lassen.
>Nun stellt sich mir die Frage, macht C++ inzwischen mehr Sinn als vor >ein paar Jahren? Ein Punkt, der mich in C etwas stört ist, dass man >keine Funktionen überlagern kann. Eigenartig. Ein Feature, das ich praktisch nie verwende. Außer in Verbindung mit schematisierten Klassen, die in vielen Fällen den Code nur aufblähen, bringt das doch nichts - also was soll das? Wenn ich Pferde und Äpfel addieren will, gibt es unter c++ die Möglichkeit eine Funktion mit Namen Addiere_Etwas ( ... ) zu implementieren. In normalem c müsste ich dann Addiere_Pferde (...) und Addiere_Aepfel (...) schreiben. Und nur kommt der alles umwerfende Effekt: "Unten" gibt es weiterhin zwei Funktionen die implementiert und gewartet werden müssen. Also bleibt als Erleichterung ein geringerer Bedarf an Fantasie bei der Namensfindung. Bei der Fehlerfindung allerdings wird etwas mehr Kreativität gefordert. Der Effekt: Manchmal geht’s manchmal nicht wird dadurch verschmiert, dass man bei gleichnamigen Aufrufen verschiedene Adressaten hat.
Das überladen von Funktionen ist auch ein sehr nützliches Features was ich gerne verwende. Wenn man Funktionen hat die das gleiche machen, aber mit unterschiedlichen Parametertüpen aufrufen möchte. Z. B.:
1 | void send(const char c) { |
2 | ...
|
3 | }
|
4 | |
5 | void send(const char* s) { |
6 | while(*s) { |
7 | send(*s++); |
8 | }
|
9 | }
|
:
Bearbeitet durch User
@amateur: Das ist genau die Mischung aus Vorurteilen und Unwissenheit, die zeigen, daß da jemand schreibt, der das nich nie ausprobiert hat. Dies wird nämlich in allen Punkte der Mangel der in C++ behoben wurde, diesem angelastet. Eine überladene Methode sorgt nämlich genau dafür, daß keine Äpfel auf Pferde addiert werden. Nennt sich Typsicherheit. Und wenn ich PferdeAddieren() und ÄpfelAddieren() brauche, dann gibt es die ja auch beide. Und daß ein Debugger die verschiedenen Aufrufsignaturen auseinander halten kann, ist auch gewährleistet. Nennt sich "Name Mangling".
Carl D. schrieb: > Eine überladene Methode sorgt nämlich genau dafür, daß keine Äpfel auf > Pferde addiert werden. Nennt sich Typsicherheit. Das hat er nicht behauptet, es ging um Pferde mit Pferden und Äpfel mit Äpfeln zu addieren, aber eben mit nur einer Funktion. So richtig gute Argumente für C++ hab ich hier noch nicht gehört. Hat jemand ein gutes praktisches Beispiel, dass die Vorzüge von C++ auf dem uC verdeutlicht?
:
Bearbeitet durch User
Julian B. schrieb: > Hat jemand ein gutes praktisches Beispiel, dass die Vorzüge von C++ auf > dem uC verdeutlicht? ... nicht nur auf µC, sondern generell: hate this schrieb: > Datenkapselung und einen typesicheren enum
Eine einfache GUI ist der Musterkandidat für Objektorientierung. Das kann man alles auch in C machen, aber es lässt sich in C++ einfach schöner umsetzen. Oder eine allgemeine Ringbuffer-Implementation: In C braucht man eine Implementation pro Datentyp, oder man arbeitet immer auf void* und muss dann eine Speicherverwaltung haben. Wenn man es nicht übertreibt (d.h. den Code aufbläht), dann ist das in C++ mit weniger hingeschriebenem Code machbar.
Christian K. schrieb: > Sobald wegen virtuellen Methoden eine Lookuptabele > angelegt werden muss, wird dadurch der Programmcode größer und man hat > Nachteile im Laufzeitverhalten. Wenn man Polymorphismus und virtuelle Methoden aber braucht, weil die Anwendung das erfordert, ist eine handgehäkelte Version in reinem C sehr wahrscheinlich nicht viel besser als das, was ein C++-Compiler macht. Letzterer ist bei sowas aber deutlich sorgfältiger als die meisten Programmierer ;)
Das schöne an C++ ist, dass man auch in "C mit Klassen" programmieren kann. Ich benutze unter anderem auch C++ auf kleinen Mikrocontrollern, vor allem folgene Dinge empfinde auf einem uC ich als Vorteile gegenüber C: - Konstruktoren/Destruktoren - namespaces - Typensichere enums - Templates - Überladung von Funktionen/Operatoren - Vererbung - Iteratoren structs habe ich fast komplett durch Klassen ersetzt, was auch die Länge der Funktionsnamen verkürzt und die Datenkapselung begünstigt. Statt
1 | DisplayWrite(Display, String); |
schreibe ich nun
1 | Display.Write(String); |
was meiner Meinung nach angenehmer und übersichtlicher ist. Hardwarenahe Dinge sind nahezu idetisch wie in C und lassen sich in C++ genau so gut kapseln. Ist halt stupides Bitgeschubse. Edit: Fast vergessen, leider gibt es keine offizielle Standardbibliothek, was sicher auch daran liegt, dass Exceptions auf kleinen uCs meist unerwünscht sind. Deswegen, habe ich die Dinge, die ich benötige, selbst programmiert/kopiert, damit ich bestehende Software nutzen kann. Einfaches Beispiel ist die Definition von size_t und der (u)int_fastXX_t Typen im std namespace.
:
Bearbeitet durch User
Da ich beruflich in Java programmiere und mit C++ auch sehr gut vertraut bin, würde ich meine AVR Projekte auch gerne in C++ schreiben. Aber dabei bin ich einige male unerwartet an die Speicher-Grenzen gestoßen. In C ist mir das noch nie passiert, deswegen bin ich wieder auf C zurück gekommen.
Stefan U. schrieb: > Aber dabei bin ich einige male unerwartet an die Speicher-Grenzen > gestoßen. In C ist mir das noch nie passiert, deswegen bin ich wieder > auf C zurück gekommen. Wie kann man unerwartet an Speichergrenzen stoßen die es in C nicht gibt? Das einzige was mir dazu einfällt ist in C++ wie in Java zu Programmieren (überall New und nicht ordentlich aufräumen) oder unüberlegte Verwendung von STL Containern (die auch viel dynamische Speicherverwaltung brauchen). Std:array zum Beispiel hat keinen Laufzeit Overhead verglichen mit c Arrays aber den ganzen STL Komfort. Einfache Klassen ermöglichen ordentliche Kapselung und saubere Namensräume ohne Kosten. Statischer Polymorhismus ermöglicht dann noch viele Vorteile von Vererbung ohne virtuelle Funktionen. Templates und Templatemetaprogrammierung ermöglichen eleganten und vom Compiler sehr gut optimierbaren Code zu generieren, der in C zu ifdef Orgien ausartet. Insbesondere in Kombination mit constexpr und Static_assert kann viel Code vom Compiler erledigt und geprüft werden ohne jemals den uC Kern zu erreichen.
Das ganz einfache Problem mit C++ ist, dass es komplexer ist als das was man als normaler Programmierer verstehen kann. Die wenigen Leute, die C++ verstehen, arbeiten in aller Regel nicht als C++ Programmierer sondern schreiben Bücher über C++, bzw arbeiten als "Sprach-Guru". Eine Programmiersprache, welche ich nicht vollständig verstehen kann, führt dazu, dass ich ggf. Fehler mache, die ich nicht vorhersehen kann. Ein typisches Beispiel sind die vielen "Gleichheitsoperatoren" in Sprachen wie PHP.
Christian B. schrieb: > Eine Programmiersprache, welche ich nicht vollständig verstehen kann, > führt dazu, dass ich ggf. Fehler mache, die ich nicht vorhersehen kann. Dann hast du aber beim Erlernen jeglicher Sprache ein Problem. Denn jede hat ihre Fallstricke und kann deshalb ja nicht benutzt werden, womit die Chance flöten geht, sie zu lernen. Ein "Devil Circle"!
Christian B. schrieb: > Das ganz einfache Problem mit C++ ist, dass es komplexer ist als das was > man als normaler Programmierer verstehen kann. Milliarden von LOC in C++ beweisen das Gegenteil. > Eine Programmiersprache, welche ich nicht vollständig verstehen kann, > führt dazu, dass ich ggf. Fehler mache, die ich nicht vorhersehen kann. Wenn Du C++ nicht verstehst, muß das nicht an C++ liegen. Was genau hast Du denn daran nicht verstanden? > Ein typisches Beispiel sind die vielen "Gleichheitsoperatoren" in > Sprachen wie PHP. Nichts gegen ein ordentliches Bashing gegen PHP, aber es als "Argument" gegen C++ zu benutzen, ist, vorsichtig gesagt, daneben.
Hermann U schrieb: > Hallo, > > ich schreibe meine Programme auf dem AVR (hauptsächliche mega328P, > mega644 und tiny841) hauptsächlich in avr-gcc. > > Nun stellt sich mir die Frage, macht C++ inzwischen mehr Sinn als vor > ein paar Jahren? Ein Punkt, der mich in C etwas stört ist, dass man > keine Funktionen überlagern kann. Das ging mit g++ auf dem AVR aber schon immer. Warum war das deiner Meinung nach denn "vor ein paar Jahren" nicht sinnvoll?
Carl D. schrieb: > Dann hast du aber beim Erlernen jeglicher Sprache ein Problem. Denn jede > hat ihre Fallstricke und kann deshalb ja nicht benutzt werden, womit die > Chance flöten geht, sie zu lernen. Ein "Devil Circle"! Naja, eine "normale" Sprache wird in einem Lehrbuch mit vielleicht 100-200 Seiten komplett beschrieben, da kann man einen vernünftigen Teil der Sprache begreifen. C++ (und seine Nachfahren) hingegen sind hoch komplex mit immer neuen Funktionen die so halb das machen was schon bestehende Funktionen gemacht haben. Es gibt ja genügend Leute die sich kritisch mit C++ befasst haben... besonders schön ist es, wenn C++ Gurus sich dazu äußern. https://www.youtube.com/watch?v=48kP_Ssg2eY C++ (uns seine Nachkommen) mag sinnvolle Anwendungen haben, die meisten Probleme in der IT werden jedoch durch die Verwendung von C++-Features eher komplexer als einfacher. Mehr Komplexität bedeutet mehr Fehler und mehr Wartungsaufwand, deshalb sollte Komplexität meiner Ansicht nach vermieden werden. Es gibt ja auch in C++ nicht das "strahlende Beispiel" für ein so richtig erfolgreiches Projekt. Bei C ist das zum Beispiel UNIX. Wenn C++-Leute ein Betriebssystem programmieren... naja die Ergebnisse sehen viele Leute ja täglich.
Christian B. schrieb: > eine "normale" Sprache Mit deinem Text, bin ich nun gar nicht einverstanden.... C/C++ ist eine normale Sprache ca 40 Jahre alt, läuft auf dem kleinsten AVR und auf den, ganze Keller füllenden, Mainframes. Man könnte sagen, dass die OOP zu früh dran geklemmt wurde. Andere Sprache verzichten z.B. auf Friends und Polymorphie. Christian B. schrieb: > mit immer neuen Funktionen Du meinst die Bibliotheken? Das werden immer mehr. Ganz normales Wachstum. Das ist bei C# nix anders. Christian B. schrieb: > Wenn > C++-Leute ein Betriebssystem programmieren... naja die Ergebnisse sehen > viele Leute ja täglich. Verstehe ich nicht... Kenne kein in C++ geschriebenes Betriebssystem.... Christian B. schrieb: > Es gibt ja auch in C++ nicht das "strahlende Beispiel" für ein so > richtig erfolgreiches Projekt. Unmengen an Desktopanwendungen beweisen das Gegenteil. Nur weil da nicht in jedem Dialog Fensterchen C++ steht, sind sie nicht in C++ geschrieben?
Ulrich F. schrieb: > Christian B. schrieb: >> eine "normale" Sprache > Mit deinem Text, bin ich nun gar nicht einverstanden.... > > C/C++ ist eine normale Sprache "C/C++" ist gar keine Sprache. Es gibt die Sprache C und die Sprache C++. > ca 40 Jahre alt, läuft auf dem kleinsten AVR und auf den, ganze Keller > füllenden, Mainframes. > Mann könnte sagen, dass die OOP zu früh dran geklemmt wurde. Andere > Sprache verzichten z.B. auf Friends und Polymorphie. Polymorphie ist so ziemlich das grundlegendste Element der objektorientierten Programmierung. > Christian B. schrieb: >> mit immer neuen Funktionen > Du meinst die Bibliotheken? Schau dir mal C++11 im Vergleich zu C++98 an. Da gibt es neben den erweiterten Bibliotheken auch enorm viele neue Funktionalitäten im Sprachkern selbst. Siehe https://en.wikipedia.org/wiki/C++11#Extensions_to_the_C.2B.2B_core_language Viele davon halte ich durchaus für sinnvoll, aber da man zu alten Versionen kompatibel sein will und dehsalb veraltete Konstrukte nicht wegwirft, wird die Sprache dadurch auch enorm umfangreich und komplex. > Christian B. schrieb: >> Wenn >> C++-Leute ein Betriebssystem programmieren... naja die Ergebnisse sehen >> viele Leute ja täglich. > Verstehe ich nicht... > Kenne kein in C++ geschriebenes Betriebssystem.... Naja, die Frage ist, wie man "Betriebssystem" definiert. Bezieht sich das auf den Kernel, die Treiber, die Oberfläche, die Systemtools, ...? Oder alles zusammen? Ich nutze Kubuntu, und das darin verwendete KDE ist nahezu komplett in C++ geschrieben.
Rolf M. schrieb: > Polymorphie ist so ziemlich das grundlegendste Element der > objektorientierten Programmierung. Vielleicht habe ich das falsche Wort verwendet... Mehrfachvererbung war gemeint. Rolf M. schrieb: > Funktionalitäten Er/Sie/Es sprach von Funktionen! Rolf M. schrieb: > Ich nutze Kubuntu, und das darin verwendete KDE ist nahezu komplett in > C++ geschrieben. Sach ich ja... Desktop. Ist bei Windoofs nicht viel anders.
Christian B. schrieb: > C++ (uns seine Nachkommen) mag sinnvolle Anwendungen haben, die meisten > Probleme in der IT werden jedoch durch die Verwendung von C++-Features > eher komplexer als einfacher. Ähm. Wenn ein Programm durch die Verwendung bestimmter Sprachmittel komplexer wird als ohne, dann liegt der Fehler nicht in der Programmiersprache, sondern ausschließlich beim Programmierer. Gerade im Fall von C++ ist das überhaupt kein Argument, denn schließlich ist jedes [1] C-Programm ein gültiges C++ Programm. Man kann also in C++ exakt genauso "unkomplex" programmieren wie in C. Das übrigens im krassen Gegensatz zu Java, das den Programmierer zwingt, alles in sein Objektschema zu pressen. Auch dann wenn es ganz offensichtlich unsinnig ist [2]. Wenn irgendein Sprachfeature von C++ das Programm also komplexer (unübersichtlicher, weniger lesbar) machen würde, dann muß sich der Programmierer fragen lassen, warum er es denn überhaupt verwendet. Allerdings zeigt die Praxis eher das Gegenteil. Die meisten C-Programme lassen sich durch den Gebrauch von C++ Features kürzer und lesbarer hinschreiben. [1] offensichtliche Ausnahme: neue Schlüsselworte in C++. Die darf man in einem C-Programm natürlich nicht als Bezeichner verwenden, wenn man es mit dem C++ Compiler übersetzen will. [2] klassisches Beispiel: main(). Ein Programm hat genau eine main() Funktion. Aber weil Java keine alleinstehenden Funktionen erlaubt, muß man eine Dummy-Klasse mit einer statischen main() Methode verwenden. Bescheuert³
Ulrich F. schrieb: > Rolf M. schrieb: >> Polymorphie ist so ziemlich das grundlegendste Element der >> objektorientierten Programmierung. > Vielleicht habe ich das falsche Wort verwendet... > Mehrfachvererbung war gemeint. Ach so. Andere Sprachen wie Java haben so was ähnliches auch, nur ist es halt eingeschränkt und heißt anders. > Rolf M. schrieb: >> Funktionalitäten > Er/Sie/Es sprach von Funktionen! Ich vermute, dass das nicht im Sinne von C-Funktionen, sondern allgemein im Sinne von Funktionalitäten gemeint ist. > Rolf M. schrieb: >> Ich nutze Kubuntu, und das darin verwendete KDE ist nahezu komplett in >> C++ geschrieben. > Sach ich ja... > Desktop. > > Ist bei Windoofs nicht viel anders. Dann ist aber die pauschale Aussage, es sei nicht in C++ geschrieben, falsch.
Rolf M. schrieb: > Dann ist aber die pauschale Aussage, es sei nicht in C++ geschrieben, > falsch. Vorsicht mit den Äpfeln und den Birnen... ;-) Christian B. schrieb: > Bei C ist das zum Beispiel UNIX. Ich denke Christian meint den Unix Kern. Der ist in C geschrieben. Man könnte sogar sagen, dafür wurde C erfunden. Der Windows Kern ist ebenso in C geschrieben, soweit mir bekannt. Rolf M. schrieb: > und heißt anders. Interfaces !?!? Mir persönlich gefällt das VIEL besser (aber was mir gefällt ist ja hier nicht gefragt worden) Rolf M. schrieb: > "C/C++" ist gar keine Sprache. Es gibt die Sprache C und die Sprache > C++. Liegt ein bisschen daran, ob man die Unterschiede betonen möchte, oder die Gemeinsamkeiten. Zu Zeiten meiner ersten C Kontakte war C nicht viel mehr als ein erweiterter Macro Assembler. Und später wurden dann ersten die OOP Erweiterungen als Präprozessor Statements dran geklebt. Lang ist es her....
Axel S. schrieb: > Wenn irgendein Sprachfeature von C++ das Programm also komplexer > (unübersichtlicher, weniger lesbar) machen würde, dann muß sich der > Programmierer fragen lassen, warum er es denn überhaupt verwendet. Zumindest wird es immer in dem Sinn komplexer, dass man diese Features auch alle kennen muss, um das Programm zu verstehen. Die Anwendung der Sprache generell wird also komplexer. Wenn das Programm selbst dadurch komplexer wird, gebe ich dir recht. Dann ist was schief gelaufen. > [1] offensichtliche Ausnahme: neue Schlüsselworte in C++. Die darf man > in einem C-Programm natürlich nicht als Bezeichner verwenden, wenn man > es mit dem C++ Compiler übersetzen will. Das ist nicht die einzige Ausnahme. C hat sich unabhängig von C++ weiterentwickelt, und so gibt es auch C-Features, die C++ so nicht hat, z.B. VLAs. > [2] klassisches Beispiel: main(). Ein Programm hat genau eine main() > Funktion. Aber weil Java keine alleinstehenden Funktionen erlaubt, muß > man eine Dummy-Klasse mit einer statischen main() Methode verwenden. > Bescheuert³ Nicht nur main(). Teils gibt es auch Hilfsfunktionen, die eigentlich freistehend sein sollten. In Java muss man die auch irgendwie in Dummy-Klassen zusammenfassen. Eine Klasse, die niemals instanziiert wird und von der auch nie geerbt wird, geht für mich irgendwie am Sinn von Klassen vorbei. > Rolf M. schrieb: >> und heißt anders. > Interfaces !?!? > Mir persönlich gefällt das VIEL besser > (aber was mir gefällt ist ja hier nicht gefragt worden) Ich find's irgendwie blöd. In C++ nehme ich eine abstrakte Basisklasse und kann damit das gleiche machen, nur daß die auch Code enthalten darf. In Java darf ich nur von einer Klasse ableiten, die Code enthält. Alles andere, von dem ich ableite (die Interfaces) müssen leer sein. Ich sehe keinen besonderen Sinn in einer derartigen Einschränkung. > Rolf M. schrieb: >> "C/C++" ist gar keine Sprache. Es gibt die Sprache C und die Sprache >> C++. > Liegt ein bisschen daran, ob man die Unterschiede betonen möchte, oder > die Gemeinsamkeiten. Ich mag es eben nicht, dass die beiden so häufig in einen Topf gesteckt und als eine einzelne Sprache bezeichnet werden. Spricht ja auch keiner von "der Sprache C#/Java".
:
Bearbeitet durch User
Ich habe es wieder aufgegeben bzw. musste mir wegen der Unzulänglichkeit des gcc, vtables in das flash zu legen, eine ähnliche Struktur schaffen, indem ich massiv Templates genutzt habe. Mein Fazit: templates & co sind angenehm und machen vieles einfacher, virtuelle Klassen machen Probleme durch vermehrten RAM-Verbrauch, weil der Compiler mit der Architektur des AVR nicht gut umgehen kann. Ergo, ich nutze seit dem eher STM und dann C++ oder nur noch bei kleineren Projekten AVR und eine geschrumpfte Untermenge von C++. Dort nutze ich vor allem Dinge wie z.B. Templates für Ringpuffer.
Christian K. schrieb: > Das überladen von Funktionen ist auch ein sehr nützliches Features was > ich gerne verwende. Wenn man Funktionen hat die das gleiche machen, aber > mit unterschiedlichen Parametertüpen aufrufen möchte. > Z. B.:
1 | void send(const char c) { |
2 | > ... |
3 | > } |
4 | >
|
5 | > void send(const char* s) { |
6 | > while(*s) { |
7 | > send(*s++); |
8 | > } |
9 | > } |
Und wie sendest du einen String, der im Flash steht?
Axel S. schrieb: > klassisches Beispiel: main(). Ein Programm hat genau eine main() > Funktion. Aber weil Java keine alleinstehenden Funktionen erlaubt, muß > man eine Dummy-Klasse mit einer statischen main() Methode verwenden. > Bescheuert³ Und warum sollte man für genau diesen Einzelfall (gibt es pro Programm genau einmal) eine eigene Syntax/Sprachfeature einbauen, wo es doch genauso gut mit der bestehenden Funktionalität klappt? Das erhöht doch nur sinnlos die Komplexität. Rolf M. schrieb: > Nicht nur main(). Teils gibt es auch Hilfsfunktionen, die eigentlich > freistehend sein sollten. In Java muss man die auch irgendwie in > Dummy-Klassen zusammenfassen. Eine Klasse, die niemals instanziiert wird > und von der auch nie geerbt wird, geht für mich irgendwie am Sinn von > Klassen vorbei. Es sollte so wenig wie möglich freistehend = global sein. Ist doch absolut sinnvoll, Hilfsmethoden zu strukturieren und zu verpacken. Und auch wenn die statisch sind, so sind sie durch die Klassen doch gut gekapselt. In der OO-Lehre steht meist die Vererbung im Vordergrund. Für mich persönlich spielt die aber ganz und gar nicht die Hauptrolle bei der OO-Programmierung. Man muss eben nicht alles in instanziierte und sieben Mal abgeleitete und Interfaceüberladene Methoden stecken.
Jan H. schrieb: > Es sollte so wenig wie möglich freistehend = global sein. Ist doch > absolut sinnvoll, Hilfsmethoden zu strukturieren und zu verpacken. Und > auch wenn die statisch sind, so sind sie durch die Klassen doch gut > gekapselt. (Dafür gibt es in C++ einen namespace. Es spricht natürlich nichts prinzipielles dagegen, wenn man keinen namespace hat, dafür ein Klasse zu nehmen und nichts reinzuschreiben, wenn man es nicht braucht.) Aber interfaces in Java sind in der Tat eine Einschränkung, weil man denselben Code ggf. in mehreren Instanzen schreiben muß - nur damit der Compiler einfacher gebaut werden kann. Viele Java-Programmierer finden interfaces toll, und realisieren gar nicht, daß es kastrierte Klassen sind.
Rolf M. schrieb: > Axel S. schrieb: >> Wenn irgendein Sprachfeature von C++ das Programm also komplexer >> (unübersichtlicher, weniger lesbar) machen würde, dann muß sich der >> Programmierer fragen lassen, warum er es denn überhaupt verwendet. > > Zumindest wird es immer in dem Sinn komplexer, dass man diese Features > auch alle kennen muss, um das Programm zu verstehen. Unsinn. Hier ging es darum ob es sinnvoll ist, selber C++ zu programmieren. Nicht darum, fremde C++ Programme zu verstehen. Und wer in seinen eigenen Programmen Sprachfeatures verwendet die er nicht versteht, der ist alles, aber kein Programmierer. > Das ist nicht die einzige Ausnahme. C hat sich unabhängig von C++ > weiterentwickelt, und so gibt es auch C-Features, die C++ so nicht hat, > z.B. VLAs. Du beliebst zu scherzen. VLA sind im GCC schon seit Ewigkeiten als Erweiterung drin. Und funktionieren selbstverständlich in C++ genauso wie in C (ok, fast: gcc muß man explizit sagen daß er VLA akzeptieren soll, für g++ ist das der Default): cat test.c
1 | #include <stdio.h> |
2 | |
3 | void make_array(int n) |
4 | {
|
5 | int the_array[n]; |
6 | for (int i=0; i<n; i++) |
7 | the_array[i]= i; |
8 | for (int i=0; i<n; i++) |
9 | printf("%d -> %d\n", i, the_array[i]); |
10 | }
|
11 | |
12 | int main(void) |
13 | {
|
14 | make_array(10); |
15 | return 0; |
16 | }
|
1 | /tmp $gcc -std=c99 test.c -o test_c |
2 | |
3 | /tmp $g++ test.c -o test_c++ |
4 | |
5 | /tmp $ls -l test* |
6 | -rw-r--r-- 1 axel axel 233 Dec 19 13:49 test.c |
7 | -rwxr-xr-x 1 axel axel 7008 Dec 19 13:53 test_c* |
8 | -rwxr-xr-x 1 axel axel 7248 Dec 19 13:53 test_c++* |
9 | |
10 | /tmp $./test_c |
11 | 0 -> 0 |
12 | 1 -> 1 |
13 | 2 -> 2 |
14 | 3 -> 3 |
15 | 4 -> 4 |
16 | 5 -> 5 |
17 | 6 -> 6 |
18 | 7 -> 7 |
19 | 8 -> 8 |
20 | 9 -> 9 |
21 | |
22 | /tmp $./test_c++ |
23 | 0 -> 0 |
24 | 1 -> 1 |
25 | 2 -> 2 |
26 | 3 -> 3 |
27 | 4 -> 4 |
28 | 5 -> 5 |
29 | 6 -> 6 |
30 | 7 -> 7 |
31 | 8 -> 8 |
32 | 9 -> 9 |
Axel S. schrieb: > Du beliebst zu scherzen. VLA sind im GCC schon seit Ewigkeiten als > Erweiterung drin. Genau, als Erweiterung zum Standard. Ich verwende ungern Compilererweiterungen, denn ich habe keine Lust, dass ein Programm mit Compiler X kompiliert werden kann, mit Compiler Y aber zu Fehlern führt. GCC ist nicht das Mass aller Dinge.
Klaus W. schrieb: > Aber interfaces in Java sind in der Tat eine Einschränkung, weil man > denselben Code ggf. in mehreren Instanzen schreiben muß - nur damit der > Compiler einfacher gebaut werden kann. > > Viele Java-Programmierer finden interfaces toll, und realisieren gar > nicht, daß es kastrierte Klassen sind. Da habe ich Schmerzen mit.... In der Regel haben Sprachen ohne Mehrfachvererbung irgend ein Interface Konzept. Vielleicht auch manche beides, ka. Mehrfachvererbung bringt auch so seine Probleme mit sich... Es wurde in C++ eingebaut, aber ich glaube, dass sich die Entwickler immer noch reihenweise dafür selber in den Arsch beißen. Jetzt kommen sie nicht mehr weg davon, ohne dass Tonnen von Code unbrauchbar werden. > Compiler einfacher gebaut > kastrierte Klassen Ein sehr subjektiver Blickwinkel
Jan H. schrieb: > Axel S. schrieb: >> klassisches Beispiel: main(). Ein Programm hat genau eine main() >> Funktion. Aber weil Java keine alleinstehenden Funktionen erlaubt, muß >> man eine Dummy-Klasse mit einer statischen main() Methode verwenden. >> Bescheuert³ > > Und warum sollte man für genau diesen Einzelfall (gibt es pro Programm > genau einmal) eine eigene Syntax/Sprachfeature einbauen, wo es doch > genauso gut mit der bestehenden Funktionalität klappt? Die übliche Formulierung ist "Würgaround" oder "übler Hack". Nicht "bestehende Funktionalität". > Das erhöht doch nur sinnlos die Komplexität. Ich finde es im Gegensatz unnötig komplex, eine Dummyklasse definieren zu müssen, die als einzigen Member eine main() Methode hat. Und selbstverständlich ist main() keineswegs ein Einzelfall. Man könnte einen ganzen Thread damit füllen. Aber nur für dich noch ein paar: min(), max(), sort() Und um wieder zum Thema zurück zu kommen: natürlich will man min() und max() als typsichere C++ Templates schreiben und nicht als C Makro. > Es sollte so wenig wie möglich freistehend = global sein. Sagt wer? Und wieso ist freistehend = global? Namespaces existieren. > In der OO-Lehre steht meist die Vererbung im Vordergrund. Für mich > persönlich spielt die aber ganz und gar nicht die Hauptrolle bei der > OO-Programmierung. Man muss eben nicht alles in instanziierte und sieben > Mal abgeleitete und Interfaceüberladene Methoden stecken. Ich würde mal sagen, daß OO viel zu oft als Allheilmittel angesehen wird. Ist es aber nicht. Es gibt Dinge die man OO besser ausdrücken kann. Und andere für die das nicht gilt. Eine gute Programmiersprache sollte dem Rechnung tragen indem sie beide (bzw. überhaupt mehrere) Paradigmen zur Wahl stellt. Das machen eigentlich alle modernen Programmiersprachen. Und C++
be s. schrieb: > Axel S. schrieb: >> Du beliebst zu scherzen. VLA sind im GCC schon seit Ewigkeiten als >> Erweiterung drin. > > Genau, als Erweiterung zum Standard. Ich verwende ungern > Compilererweiterungen, denn ich habe keine Lust, dass ein Programm mit > Compiler X kompiliert werden kann, mit Compiler Y aber zu Fehlern führt. > GCC ist nicht das Mass aller Dinge. Da stimme ich gröstenteils zu, aber eine Erweiterung ist es nur in C++, nicht aber in C. Axel S. schrieb: > Und funktionieren selbstverständlich in C++ genauso > wie in C (ok, fast: gcc muß man explizit sagen daß er VLA akzeptieren > soll, für g++ ist das der Default) Ich finde, dass man dem GCC extra sagen muss er soll sich an den Standard XY halten wirklich schlecht. Ich verstehe nicht warum Sie momentan gnu++98 bzw. gnu99 statt c++98 und c99 als default setzen. ----------------- Ich finde C++ eigentlich ganz gut, aber: * Ich vermisse einige komfortable C Features, wie z.B. Variable Length Arrays und designated initializers. * Mir gefällt nicht, dass ich für gewisse Templates die Funktionen inline im Header in der Klasse haben muss, und so Code und Interface nichtmehr sauber trennen kann. * Dass es statt Interfaces nur Abstrakte Klassen gibt, dies führt zu Problemen wie dem Diamond-Problem. Besser wäre es gewesen, wenn Daten, Funktionsinterfaces und Implementierungen getrennt hätte, aber nicht so wie in "go", die generieren overhead. * Zu viele Wege führen nach Rom. Soll ich nun eine "Disc<CD_ROM>" (Template+enum), eine "class CDRom : Disc" (Vererbung) oder eine "Disc(CD_ROM)" (Constructor+enum) erstellen? Egal, ich nehmen C++11 und schreibe "1024_memory"! (User-defined literal) * Es gibt keinen einfachen weg zu Prüfen, ob ein Feature unterstützt wird, und jenachdem Compielerunabhängig mit eigenen Implementierungen zu Ersetzen. Das gilt allerdings auch für C. Man stelle sich nur mal for, man will std::thread verwenden, aber wenn es das nicht gibt ein Wrapper schreiben mit POSIX Pthreads, aber auf der ARM Version immer einen Wrapper auf irgendwelche Rtos funktionen verwenden. Was nun? * Kompilerabhängige Dinge wie Name Mangling, für Libraries pures Gift, und dann kann man Klassen nichteinmal in ein extern C setzen... * Komplexität, Beispiel: lvalue, rvalue und rvalue referenzen, ich will möglichst jeden Kopiervorgang und Redundanz verhindern. Eine Funktion soll deshalb sowohl eine lvalue als auch eine rvalue als Argument nehmen können; Verwende ich keine Referenz als Argumenttype, wird Kopiert. Verwende ich eine, kann ich keine rvalue übergeben. Verwende ich eine rvalue-referenz, kann ich keine lvalue mehr übergeben, und überlade ich die Funktion, gibt es uneindeutige Situationen. Ein schönes Happy End gibt es nicht, entweder man nutzt die Kopierveriante, oder die Referenz variante und speichert rvalues in lvalues vor dem Aufruf... Was ich noch Praktisch fände, und es noch in keiner Programmiersprache gibt: * Compile Time Reflection. Damit könnte man zur Compile Time Code zur Serialisierung/Deserialisierung von Klassen, etc. erstellen. Ich glaube dass wird gerade für C++1z/C++17 diskutiert, aber ich kann mir nicht vorstellen, wie die dass auchnoch brauchbar in die Sprache hineinzwägen wollen, ist mir schleierhaft. * IO in Templates zur Compile Time
:
Bearbeitet durch User
Ulrich F. schrieb: > Mehrfachvererbung bringt auch so seine Probleme mit sich... > Es wurde in C++ eingebaut, aber ich glaube, dass sich die Entwickler > immer noch reihenweise dafür selber in den Arsch beißen. Jetzt kommen > sie nicht mehr weg davon, ohne dass Tonnen von Code unbrauchbar werden. > Wenn man meint nur Einfachvererbung und Interfaces zu brauchen, kann man das in jedem C++ Projekt jederzeit so machen. Gibt ja abstrakte Basisklassen als Interface. Das ist der große Unterschied zwischen Sprachen wie Java und C++. Java verbietet einfach viele "gefährliche" und übermäßig komplexen Sachen, baut Laufzeitprüfungen und GCs ein, C++ erlaubt alles was der Compiler dem Programmierer irgendwie ermöglichen kann. Das erstere hat sicher viel Code besser gemacht, aber Grenzen in Performance oder Eleganz lotet sicher kein Java Programm aus. Insbesondere die erbärmlichen Implementierung von Geneerics in Java stimmt jeden traurig der die Macht der C++ Templates kennengelernt hat. Andererseits sind die Compilerfehler bei Templateproblemen immer noch was für Hardcoreprogrammierer.;)
Scelumbro schrieb: > Wenn man meint nur Einfachvererbung und Interfaces zu brauchen, kann man > das in jedem C++ Projekt jederzeit so machen. Gibt ja abstrakte > Basisklassen als Interface. Aber diese lösen dass Diamond-Problem nicht, oder? https://de.wikipedia.org/wiki/Diamond-Problem
:
Bearbeitet durch User
Daniel A. schrieb: > Scelumbro schrieb: >> Wenn man meint nur Einfachvererbung und Interfaces zu brauchen, kann man >> das in jedem C++ Projekt jederzeit so machen. Gibt ja abstrakte >> Basisklassen als Interface. > > Aber diese lösen dass Diamond-Problem nicht, oder? > https://de.wikipedia.org/wiki/Diamond-Problem Mit virtueller Vererbung geht das. Also anstelle class B : public A class C : public A einfach class B : public virtual A class C : public virtual A verwenden.
Jan H. schrieb: > Rolf M. schrieb: >> Nicht nur main(). Teils gibt es auch Hilfsfunktionen, die eigentlich >> freistehend sein sollten. In Java muss man die auch irgendwie in >> Dummy-Klassen zusammenfassen. Eine Klasse, die niemals instanziiert wird >> und von der auch nie geerbt wird, geht für mich irgendwie am Sinn von >> Klassen vorbei. > > Es sollte so wenig wie möglich freistehend = global sein. Ist doch > absolut sinnvoll, Hilfsmethoden zu strukturieren und zu verpacken. In C++ gibt's dafür Namespaces. Da muss man nicht extra eine Pseudoklasse für erstellen. > Man muss eben nicht alles in instanziierte und sieben Mal abgeleitete und > Interfaceüberladene Methoden stecken. Muß man nicht, aber dann gehört es eben auch nicht in eine Klasse. Axel S. schrieb: >> Das ist nicht die einzige Ausnahme. C hat sich unabhängig von C++ >> weiterentwickelt, und so gibt es auch C-Features, die C++ so nicht hat, >> z.B. VLAs. > > Du beliebst zu scherzen. VLA sind im GCC schon seit Ewigkeiten als > Erweiterung drin. Und funktionieren selbstverständlich in C++ genauso > wie in C In C++ sind sie allerdings eine nicht-Standard-Erweiterung. In C gehören sie zum Sprachumfang dazu. Es ging um die pauschale Behauptung, jedes C-Programm sei automatisch auch ein C++-Programm. Wenn man beliebige Erweiterungen akzeptiert, gilt das natürlich immer. > /tmp $gcc -std=c99 test.c -o test_c > > /tmp $g++ test.c -o test_c++ Hmm, für C schaltest du also explizit Konformität zur Norm ein, für C++ nicht. Wenn du das da auch tätest (z.B. -std=c++11), sähe es anders aus. Ulrich F. schrieb: > Mehrfachvererbung bringt auch so seine Probleme mit sich... > Es wurde in C++ eingebaut, aber ich glaube, dass sich die Entwickler > immer noch reihenweise dafür selber in den Arsch beißen. Also ich finde sie sehr praktisch und beiße mir dafür nirgendwo rein. Daniel A. schrieb: > * Mir gefällt nicht, dass ich für gewisse Templates die Funktionen > inline im Header in der Klasse haben muss, und so Code und Interface > nichtmehr sauber trennen kann. Musst du doch nicht. Du kannst da auch die Implementation in ein separates File schreiben. Nur die Art, wie es eingebunden werden muss, ist anders. > und dann kann man Klassen nichteinmal in ein extern C setzen... Wie soll das auch gehen? Klassen unterstützt C nicht.
Rolf M. schrieb: > Jan H. schrieb: >> und dann kann man Klassen nichteinmal in ein extern C setzen... > Wie soll das auch gehen? Klassen unterstützt C nicht. extern "C" verändert die C++ Linkage, aber es bedeutet nicht dass nun C-Code folgt. Falls dem nicht so ist lass ich mich gerne aufklären.
Johann L. schrieb: > Rolf M. schrieb: >> Jan H. schrieb: >>> und dann kann man Klassen nichteinmal in ein extern C setzen... >> Wie soll das auch gehen? Klassen unterstützt C nicht. > > extern "C" verändert die C++ Linkage, aber es bedeutet nicht dass nun > C-Code folgt. Nein, aber es folgt Code, der direkt so von C aus aufgerufen werden kann. Wie soll man von C aus denn die Klasse instanziieren? Wie soll man ihre Member aufrufen? Wie soll der C-Compiler dafür sorgen, dass die Destruktoren aufgerufen werden, wenn die Instanz zerstört wird?
Rolf M. schrieb: > Wie soll man von C aus denn die Klasse instanziieren? Manuell, also z.B.
1 | struct Klass x; |
2 | Klass_construct(x); |
Man nimmt einfach ein Struct mit den selben Membern in der selben Reihenfolge. Mit ein wenig Präprozessormagie ist das kein Problem > Wie soll man ihre Member aufrufen? Man müsste auf virtuelle Methoden und überladung verzichten, aber ansonsten würde man aus x.y(z) ein z(x,y). > Wie soll der C-Compiler dafür sorgen, dass die Destruktoren aufgerufen werden, > wenn die Instanz zerstört wird? Garnicht, man macht es Manuell:
1 | Klass_denstruct(x); |
Ich musste ewig suchen, aber es folgt ein Link, wo ich eine Binärkompatible c version einer C++ Klasse Präsentiere: Beitrag "Re: This Pointer"
:
Bearbeitet durch User
Daniel A. schrieb: > * Komplexität, Beispiel: lvalue, rvalue und rvalue referenzen, ich will > möglichst jeden Kopiervorgang und Redundanz verhindern. Eine Funktion > soll deshalb sowohl eine lvalue als auch eine rvalue als Argument nehmen > können; Verwende ich keine Referenz als Argumenttype, wird Kopiert. > Verwende ich eine, kann ich keine rvalue übergeben. Verwende ich eine > rvalue-referenz, kann ich keine lvalue mehr übergeben, und überlade ich > die Funktion, gibt es uneindeutige Situationen. Ein schönes Happy End > gibt es nicht, entweder man nutzt die Kopierveriante, oder die Referenz > variante und speichert rvalues in lvalues vor dem Aufruf... Ja rvalues sind kompliziert aber deine Erläuterungen stimmen nicht ganz. Wenn deine Funktion sowohl lvalues als auch rvalues nehmen soll, dann nimmt man einfach eine normale (lvalue) const Referenz. Oder wenn du sowieso eine Kopie brauchst dann einfach Call by Value. Der Fall das man die gleiche Funktion mit lvalue und rvalue Referenz braucht tritt meiner Meinung nach eher selten auf und dann ist auch nichts uneindeutig.
Daniel A. schrieb: > Rolf M. schrieb: >> Wie soll man von C aus denn die Klasse instanziieren? > > Manuell, also z.B.struct Klass x; > Klass_construct(x); > > Man nimmt einfach ein Struct mit den selben Membern in der selben > Reihenfolge. Mit ein wenig Präprozessormagie ist das kein Problem Was hat das jetzt mit einer Klasse, die extern "C" ist, zu tun? Natürlich kann man sich einen Wrapper schreiben, um Klassen zu benutzen. Darum ging's aber gar nicht. Es ging viel mehr um die Frage, warum Klassen nicht extern "C" sein können. Und meine Antwort war, daß C gar keine Syntax bietet, um die zu nutzen und es daher gar keinen Sinn ergibt.
@Sebastian V. O. (sebi_s) Danke für die Erlauterung, ich wusste nicht, dass dies möglich ist, da man ja keine Referenz von einer rvalue nehmen kann habe ich dies vorher nie ausprobiert. @Rolf Magnus (rmagnus) Wenn man dadurch das Name Mangeling der Methoden der Klassen abschalten könnte, könnte man mit 2 Macros standardisierte Wrapper für Klassen auf C-Strukts machen, und ich denke dies wäre speziell bei Libraries extrem nützlich.
:
Bearbeitet durch User
Rolf M. schrieb: > Axel S. schrieb: >>> Das ist nicht die einzige Ausnahme. C hat sich unabhängig von C++ >>> weiterentwickelt, und so gibt es auch C-Features, die C++ so nicht hat, >>> z.B. VLAs. >> >> Du beliebst zu scherzen. VLA sind im GCC schon seit Ewigkeiten als >> Erweiterung drin. Und funktionieren selbstverständlich in C++ genauso >> wie in C > > In C++ sind sie allerdings eine nicht-Standard-Erweiterung. In C gehören > sie zum Sprachumfang dazu. Es ging um die pauschale Behauptung, jedes > C-Programm sei automatisch auch ein C++-Programm. Ich sehe schon, es war ein Fehler, überhaupt auf diesem Nebenkriegs- schauplatz zu erscheinen. VLA braucht man in C++ kein Stück. Container mit zur Laufzeit wählbarer Größe sind in jeder OO Programmiersprache eines der der ersten Konstrukte. Wenn man also in einem C-Programm ein VLA verwendet und das dann der C++ Compiler nicht fressen mag, ist es eine der leichtesten Übungen, ein funktionales Äquivalent mit C++ Hausmitteln dafür einzusetzen. Aber wie gesagt: Nebenkriegsschauplatz. Per Design ist C++ so nah an C wie überhaupt nur möglich. Und deswegen ist jede Behauptung, man müsse in C++ komplizierter (mit C++ Sprachmitteln) programmieren als in C, auch vollkommener Unsinn. Man kann in C++ genauso programmieren wie in C. Wieviel Sinn das ergibt und wieviel Potential man damit verschenkt, das steht natürlich auf einem anderen Blatt.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.