C++ gegen C

C++ gegen C

Ursprünglich war C++ als Obermenge von C gedacht:Die Mehrheit der existierenden C-Programme sollte auch gültige C++-Programme sein. Die Standards haben sich seitdem stark voneinander entfernt, aber selbst in den alten Tagen gab es obskure Ausnahmen:

Quiz

1. Die folgende C++-Anweisung ist in C ungültig.

x = a ? b : c = d;

Wieso den? Wie können Sie es beheben?

Antwort anzeigenDie C++-Grammatik für den ternären Operator unterscheidet sich geringfügig von der C-Grammatik, indem sie als letzten Term eine Zuweisung von Exissions zulässt. Für C müssen wir „c =d“ in Klammern setzen.

2. Die folgende C-Anweisung ist in C++ ungültig.

int *a = malloc(sizeof(*a));

Wieso den? Wie können Sie es beheben?

Show AnswerC führt eine implizite Konvertierung für void * durch, während C++ dies nicht tut. Verwenden Sie eine explizite Umwandlung, um dies zu umgehen.

3. Die Deklaration:

void some_function();

ist in C und C++ gültig. Bedeutet es in beiden Sprachen dasselbe?

Antwort anzeigenIn C deklariert es eine Funktion mit einer unbekannten Anzahl von Argumenten, während es in C++ eine Funktion mit null Argumenten deklariert. Kompilieren eines solchen C-Codes mit gcc -Wstrict-Prototypen führt zu einer Warnung; Um sie zu überraschen, platziere void innerhalb der Klammern.

C neu geladen

Wie viele Filmfortsetzungen hat C++ interessante Ideen beigesteuert, aber eine schlampige Ausführung und eine willkürliche Richtung haben das Ergebnis zum Scheitern verurteilt. Das Original ist immer noch das Beste.

Zu den wertvollen Innovationen gehören // Kommentare, Inline-Funktionen, lokale Variablen für for-Schleifen und Namespaces. Die meisten anderen Funktionen sind nachteilig.

Vorlagen

Vorlagen erscheinen nützlich, sind aber zu komplex. Die Kompilierung ist langsam, teilweise aufgrund von Aufblähung:Vorlagen generieren Code für jede instanziierte Klasse. Diese Aufblähung kann zu langsamen Laufzeiten führen. Fehlermeldungen sind kryptisch. Das Mischen von Vererbung und Vorlagen wird schwierig. Außerdem müssen wir uns einer anderen Form der Überladung bewusst sein.

Obwohl Vorlagen Turing-vollständig sind, verwenden wir besser eine Sprache mit verständlicher Syntax. Außerdem muss ein Programmierer, der Template-Metaprogrammierung ausnutzt, drei Sprachen in einer Datei berücksichtigen:Templates, C++ und den iprocessor.

Kein Bezugspunkt

Referenzen können gefährlich sein, da man nicht mehr von f(x) ausgehen kann liest nur aus der Variable x . Ihr Nutzen ist fraglich, da der Array-Trick der Größe 1 meistens das „.“ eliminiert “ gegenüber „-> ” Ärger.

Verstecken von Fehlinformationen

C++ scheint das Gegenteil von dem, was es sollte, zu automatisieren und zu verbergen. Beispielsweise könnte Garbage Collection ein nützliches Feature sein, bleibt aber unbehandelt, während es Stunden dauern kann, fehlerhaften Code auszugraben, der tief in einer Klassenhierarchie in einem Kopierkonstruktor vergraben ist.

Überlastung Überlastung

C++ verfügt über Funktionsüberladung, Subtyp-Polymorphismus, implizites Casting und Template-Spezialisierung. Wie interagieren diese? Welche dieser Codezeilen sind in Kraft?

Wir haben gemischte Gefühle bezüglich der Überladung von Operatoren. Einerseits ist es eine äußerst natürliche Notation für mathematische Datenstrukturen, andererseits sind wir es gewohnt, arithmetische Operatoren gedanklich auf Maschinenbefehle abzubilden.

Mitwirkendes Casting

Implizites Casting ist ein Fehler von C, und C++ hat sich dafür entschieden, ihn zu bedienen. Darüber hinaus fügt C++ eine Cast-Syntax hinzu, die einem Funktionsaufruf ähnelt, zusammen mit 4 neuen Cast-Operatoren, die der Programmierer lernen muss. Ein Konstruktor mit einem Parameter kann leicht per Casting missbraucht werden, so dass die explicit Schlüsselwort wurde eingeführt.

Einwände gegen Objekte

Objekte waren die Hauptmotivation von C++, haben sich aber leider als seine größte Schwachstelle herausgestellt.

Konstruktoren und Destruktoren sind lästig. Da Konstruktoren keinen Wert zurückgeben können, sollten sie einfache Funktionen sein, die niemals fehlschlagen, daher ist häufig ohnehin eine Initialisierungsfunktion erforderlich. Darüber hinaus verlieren Variablendeklarationen ihre Unschuld:Man muss möglicherweise eine Klassenhierarchie weit nach oben durchqueren, um festzustellen, welche Arbeit ausgeführt wird. Außerdem rufen globale Objekte ihre Konstruktoren in einer unbestimmten Reihenfolge auf.

Die vom Compiler generierten Kopier- und Zuweisungskonstruktoren sind fast immer unerwünscht und können auch billig aussehende Operationen täuschen.

Das Private und geschützt Mechanismen zum Trennen der Schnittstelle von der Implementierung sind der Verwendung des Dateibereichs unterlegen. Typischerweise befinden sich Implementierungsdetails in den privaten oder geschützten Abschnitten einer Header-Datei, was die Definition der Schnittstelle verschmutzt und gegen das Prinzip des Verbergens von Informationen verstößt. Es ist für das Auge eines Programmierers zu einfach, undokumentierte Implementierungsdetails zu bemerken und anschließend Code zu schreiben, der sich darauf stützt. Darüber hinaus erfordert eine Änderung der Implementierung eine Änderung der Header-Datei, was wiederum die Neukompilierung aller Dateien erfordert, die sie enthalten.

Nichttechnische Vorteile

Wir sind davon ausgegangen, dass das Ziel darin besteht, effizient und effektiv zu codieren. Sind die Absichten weniger ehrenhaft, werden die Schwächen von C++ zu Stärken. Beispielsweise ist die Kompilierung langsam und wird durch die kleinsten Änderungen ausgelöst. Dies kann ausgenutzt werden, um die Freizeit bei der Arbeit zu erhöhen. Das Verschleiern von Code ist trivial, und C++-Compiler sind berüchtigt für Portabilitäts- und Interoperabilitätsprobleme, was die Arbeitsplatzsicherheit verbessert.

Weiterführende Literatur

Wir könnten weitermachen, würden aber lieber einfach ein paar Links zu diesem Thema zitieren.

Der C++ Style Guide von Google hat einige Überschneidungen mit dem oben Gesagten, ist aber weniger extremistisch.

Das UNIX-HATERS-Handbuch verunglimpft C++ mit mehr Flair und Begeisterung, wie einige seiner Abschnittstitel zeigen:„Die Assemblersprache der objektorientierten Programmierung“, „Der COBOL der 90er“, „C++ ist für C eine Lunge Krebs ist für die Lunge“. Sehr zu empfehlen.

Yossi Kreinin pflegt die C++ FQA (Frequently Questioned Answers) Lite, die beste Kritik an C++, die wir gesehen haben. Er deckt viele Verbrechen der Sprache gegen die Informatik auf. Wussten Sie zum Beispiel, dass seine Grammatik unentscheidbar ist? Oder dass die Überlastung des Bedieners durch mindestens 3 Designentscheidungen sabotiert wird? Seine wichtigste Schlussfolgerung ist unausweichlich:„Es gibt keinen Grund, C++ für neue Projekte zu verwenden“.

Linus Torvalds hat eine scharf formulierte Kritik an C++ auf einer Mailingliste gepostet.

Rob Pike kritisierte C++ und Java auf der OSCON 2010.

Einlösung

In den letzten Jahren hat sich unsere Haltung hauptsächlich aufgrund von zwei Merkmalen aufgeweicht:

  1. Typrückschluss kann Boilerplate erheblich reduzieren.
  2. Lambdas. Besser spät als nie.

Wir begrüßen auch andere Funktionen zur Verringerung des Papieraufwands, wie z. B. bereichsbasierte For-Schleifen und neue Syntax für Literale. Wenn sie jetzt nur die Implementierungsvererbung durch Typklassen im Haskell-Stil ersetzen könnten!

Quelle crypto.stanford.edu