Viele Leute haben gesagt, dass C ++ eine völlig andere Sprache ist als C, aber Bjarne selbst hat gesagt, dass C ++ eine Sprache ist, die von C erweitert wurde, daher ++
kommt die Sprache von dort. Warum sagen alle immer wieder, dass C und C ++ völlig unterschiedliche Sprachen sind? Inwiefern unterscheidet sich C von C ++ von den erweiterten Funktionen in C ++?
programming-languages
c++
c
Joshua Partogi
quelle
quelle
Antworten:
Während der 1980er Jahre, als die C ++ - Entwicklung gerade erst begann, war C ++ fast eine richtige Obermenge von C. So fing alles an.
Im Laufe der Zeit haben sich jedoch sowohl C als auch C ++ entwickelt und sind voneinander abgewichen, obwohl die Kompatibilität zwischen den Sprachen immer als wichtig angesehen wurde.
Darüber hinaus haben die technischen Unterschiede zwischen C und C ++ dazu geführt, dass die typischen Redewendungen in diesen Sprachen und die als "gute Praxis" geltenden Begriffe noch stärker voneinander abweichen.
Dies ist der treibende Faktor für Leute, die Dinge wie "Es gibt keine Sprache wie C / C ++" oder "C und C ++ sind zwei verschiedene Sprachen" sagen. Obwohl es möglich ist, Programme zu schreiben, die sowohl für einen C- als auch einen C ++ - Compiler akzeptabel sind, wird der Code im Allgemeinen weder als Beispiel für guten C-Code noch als Beispiel für guten C ++ - Code angesehen.
quelle
void *
, C ++ jedoch nie. (Hat nicht abgelehnt)Stroustrup selbst antwortet in seinen FAQ :
Es unterstützt die objektorientierte Programmierung und die generische Programmierung, die C ++ zu C "völlig anders" macht. Sie können fast reines C schreiben und es dann mit einem C ++ - Compiler kompilieren (solange Sie sich um die strengere Typprüfung kümmern). Aber dann schreiben Sie immer noch C - Sie schreiben nicht C ++.
Wenn Sie C ++ schreiben, nutzen Sie die objektorientierten Funktionen und Vorlagenfunktionen und das entspricht nicht dem, was Sie in C sehen würden.
quelle
Einfach ausgedrückt, was in C als idiomatisch angesehen wird, ist in C ++ definitiv nicht idiomatisch.
C und C ++ sind in der Praxis sehr unterschiedliche Sprachen, weil die Leute sie verwenden. C zielt auf Minimalismus ab, wobei C ++ eine sehr komplexe Sprache mit vielen Funktionen ist.
Es gibt auch einige praktische Unterschiede: C kann leicht aus so gut wie jeder Sprache aufgerufen werden und definiert häufig die ABI einer Plattform, während C ++ aus anderen Bibliotheken nur schwer zu verwenden ist. Die meisten Sprachen haben eine FFI oder Schnittstelle in C, sogar Sprachen, die in C ++ implementiert sind (z. B. Java).
quelle
Abgesehen von der offensichtlichen Tatsache, dass C ++ objektorientierte Programmierung unterstützt, haben Sie hier Ihre Antwort: http://en.wikipedia.org/wiki/Compatibility_of_C_and_C++
Dieser Artikel enthält Codebeispiele, die Dinge zeigen, die in C in Ordnung sind, aber nicht in C ++. Zum Beispiel:
Das Portieren eines C-Programms nach C ++ ist oft unkompliziert und besteht hauptsächlich aus dem Beheben von Kompilierungsfehlern (Hinzufügen von Casts, neuen Schlüsselwörtern usw.).
quelle
C ++ erweitert C nicht nur um neue Funktionen, sondern auch um neue Konzepte und Redewendungen. Auch wenn C ++ und C eng miteinander verbunden sind, müssen Sie, um effektiv in einer Sprache zu schreiben, im Stil dieser Sprache denken. Selbst der beste C-Code kann die unterschiedlichen Stärken und Redewendungen von C ++ nicht ausnutzen und ist daher eher ein schlechter C ++ - Code.
quelle
Die "erweiterten Funktionen" lassen es so klingen, als würden sie in C ++ verschiedene Makros oder ähnliches hinzufügen und das wars. Die "erweiterten Funktionen" in C ++ sind eine vollständige Überarbeitung der Sprache und ersetzen die bewährten C-Methoden vollständig, da die neuen C ++ - Funktionen so viel besser sind als die ursprünglichen C-Funktionen, dass die ursprünglichen C-Funktionen in den allermeisten Fällen vollständig und vollständig überflüssig sind . Die Annahme, dass C ++ lediglich C erweitert, deutet darauf hin, dass ein moderner Kampfpanzer ein Buttermesser für Kriegszwecke erweitert.
quelle
Der Unterschied ist, dass in C denken Sie prozedural und in C ++ denken Sie in einer objektorientierten Art und Weise. Die Sprachen sind sehr ähnlich, aber der Ansatz ist sehr unterschiedlich.
quelle
Während C ++ syntaktisch gesehen eine Supermenge von C sein kann - dh jedes Konstrukt eines C-Programms kann vom C ++ - Compiler kompiliert werden.
Sie schreiben jedoch fast nie ein C ++ - Programm so, wie Sie es mit einem C-Programm getan hätten. Die Liste kann endlos sein oder es kann jemand sein, der mehr Nachforschungen anstellt, um sie als ausführliche Berichte zu formulieren. Ich stelle jedoch nur wenige Hinweise vor, die die wesentlichen Unterschiede ausmachen.
Der Punkt des aktuellen Beitrags ist, dass C ++ die folgenden Funktionen hat, die ein guter C ++ - Programmierer als Best Practices für die Programmierung verwenden muss, obwohl es möglich ist, C-Äquivalente zu kompilieren.
Wie soll es in C ++ über C gemacht werden
Klassen & Vererbung. Das sind die wichtigsten Unterschiede, die eine systematische Objektorientierung ermöglichen, die den Programmierausdruck sehr leistungsfähig macht. Ich denke, dieser Punkt bedarf keiner besseren Erklärung. Wenn Sie in C ++ arbeiten, ist es fast immer besser, Klassen zu verwenden.
Privatisierung - Klassen und sogar Strukturen haben private Mitglieder. Dies macht Verkapselung einer Klasse möglich. Das Äquivalent in C ist die Typumwandlung des Objekts als ungültig * für die Anwendung, sodass die Anwendung keinen Zugriff auf interne Variablen hat. In C ++ können Sie jedoch Elemente sowohl mit öffentlichen als auch mit privaten Klassen haben.
Pass Bezug genommen wird . C ++ ermöglicht Änderungen basierend auf Verweisen, für die das Übergeben von Zeigern erforderlich ist. Durch das Pass-by-Reference-Verfahren wird der Code sehr sauber und vor Zeigergefahren sicherer. Sie übergeben auch einen Zeiger im C-Stil und das funktioniert - aber wenn Sie in C ++ sind, sind Sie besser dran, solange
new & delete vs. malloc und kostenlos. Die Anweisungen new () und delete () weisen nicht nur Speicher zu und geben Speicher frei, sondern ermöglichen auch die Ausführung von Code als Teil des Destruktors, der in einer Kette aufgerufen werden soll. Wenn Sie C ++ verwenden - es ist eigentlich BAD zu verwenden malloc und kostenlos.
IO-Typen und Betreiber Überlastung Operator Überlastung make Code lesbar oder intuitiver, wenn gut gemacht. Gleiches gilt für die Operatoren << und >> io. Die C-Methode hierfür wäre die Verwendung von Funktionszeigern - dies ist jedoch unübersichtlich und nur für fortgeschrittene Programmierer.
Mit "string". Das Zeichen * von C funktioniert überall. C und C ++ sind also ziemlich gleich. Wenn Sie sich jedoch in C ++ befinden, ist es immer viel besser (und sicherer), String-Klassen zu verwenden, die Sie vor den Gefahren bewahren, die ein Überlaufen von Arrays mit fast allen Dingen mit sich bringt.
Features, die ich in C ++ 1 immer noch nicht mag. Templates - Obwohl ich in vielen Codes keine umfangreichen Templates verwende, kann es sich für Bibliotheken als sehr leistungsfähig herausstellen. Es gibt fast kein Äquivalent davon in C. Aber an einem normalen Tag - besonders , wenn Sie mathematisch tun fehlt.
Dinge, die ich an C mag und in C ++ vermisse
Polymorphe Algorithmen unter Verwendung von Funktionszeigern. In C, wenn Sie komplexe Algorithmen laufen - einige Male können Sie Reihe von Funktionszeiger verwenden. Dies macht echten Polymorphismus auf mächtige Weise. Wenn Sie in C ++ sind Sie CAN - Funktionszeiger verwenden - aber das ist schlecht. Sie sollten nur Methoden anwenden - sonst sollten Sie darauf vorbereitet sein, chaotisch zu werden. Die einzige Form des Polymorphismus in C ++ - Klassen ist das Überladen von Funktionen und Operatoren, aber das ist ziemlich einschränkend.
Einfache Fäden. Beim Erstellen Fäden pThreads waren - es ist ganz einfach und überschaubar. Es wird, wenn Sie Threads erstellen müssen, die für die Klassen "privat" sein sollen (damit sie Zugriff auf private Mitglieder haben). Es gibt Boost- Frameworks - aber nichts in C ++.
Dipan.
quelle
Bestimmte Sprachfunktionen, auch wenn sie Ergänzungen sind, können die ganze Art und Weise ändern, die Sprache praktisch verwendet werden muss. Als ein Beispiel betrachten diesen Fall:
Wenn die obigen Codefunktionen in C implementiert beteiligt Aufruf ++, könnten wir in einer Welt von Schwierigkeiten, wie eine dieser Funktionsaufrufe werfen kann, und wir werden nie den Mutex in den Ausnahmeweg freischalten.
Destruktoren sind nicht länger praktisch, um Programmierern zu helfen, zu diesem Zeitpunkt nicht zu vergessen, Ressourcen freizugeben. RAII wird zu einer praktischen Anforderung, da es aus menschlicher Sicht nicht machbar ist, jede einzelne Codezeile zu antizipieren, die nicht-triviale Beispiele enthalten kann (ganz zu schweigen davon, dass diese Zeilen möglicherweise nicht jetzt, sondern möglicherweise später mit Änderungen ausgegeben werden). Nehmen Sie ein anderes Beispiel:
Solcher Code ist zwar in C im Allgemeinen harmlos, aber in C ++ ist er wie ein Höllenfeuer, weil die
memcpy
Bulldozer über die Bits und Bytes dieser Objekte hinweggehen und Dinge wie Kopierkonstruktoren umgehen. Solche Funktionen wiememset
,realloc
,memcpy
usw., während tägliche Werkzeuge unter den Entwicklern C verwendet , die Dinge in eine ziemlich homogenen Art und Weise von Bits zu suchen und Bytes im Speicher ist nicht harmonisch mit dem immer komplexen und reichem Typ - System von C ++. C ++ unterstützt eine viel abstraktere Sicht auf benutzerdefinierte Typen.Auf diese Weise kann C ++ für jeden, der es richtig verwenden möchte, nicht mehr als bloße "Obermenge" von C betrachtet werden. Diese Sprachen erfordern eine ganz andere Denkweise, Disziplin und Denkweise, um es am effektivsten einsetzen zu können .
Ich bin nicht in dem Lager, das C ++ in jeder Hinsicht als besser ansieht, und tatsächlich sind die meisten meiner Lieblingsbibliotheken von Drittanbietern aus irgendeinem Grund C-Bibliotheken. Ich weiß nicht genau warum, aber C-Bibliotheken sind in der Regel eher minimalistisch (vielleicht, weil die Entwickler aufgrund des Fehlens eines so umfangreichen Typsystems mehr auf die Bereitstellung der erforderlichen Minimalfunktionalität fokussiert sind, ohne große und vielschichtige Abstraktionen zu erstellen). Obwohl ich sie oft nur mit C ++ - Wrappern umhülle, um ihre Verwendung für meine Zwecke zu vereinfachen und anzupassen, ist mir diese minimalistische Natur selbst dann vorzuziehen. Ich liebe Minimalismus wirklich als attraktives Merkmal einer Bibliothek für diejenigen, die sich die zusätzliche Zeit nehmen, um nach solchen Eigenschaften zu suchen, und vielleicht neigt C dazu, dies zu fördern.
Ich für C ++ weit mehr als oft nicht, aber ich bin eigentlich für die größte binäre Kompatibilität zu verwenden C-APIs eher häufig erforderlich (und für FFI), obwohl ich sie oft in C implementieren ++ trotz C für die Header verwendet wird. Aber manchmal, wenn Sie wirklich Low-Level gehen, wie auf das Niveau eines Speicherzuordner oder sehr Low-Level-Datenstruktur (und ich bin sicher, es gibt weitere Beispiele unter denen, die Programmierung tun eingebettet), kann es manchmal hilfreich sein, zu sein davon ausgehen können, dass die Typen und Daten, die Sie gerade arbeiten fehlen bestimmte Funktionen wie vtables, costructors und Destruktoren, so dass wir sie als Bits behandeln können und Bytes mischen um, kopieren, frei, neu zuweisen. Bei ganz besonders einfachen Problemen kann es manchmal hilfreich sein, mit einem viel einfacheren Typensystem zu arbeiten, das C bereitstellt.
Eine Klarstellung
Ein interessanter Kommentar hier wollte ich ein wenig mehr in die Tiefe reagieren (finde ich die Kommentare hier sind so streng auf Zeichen):
Das ist ein wichtiger Punkt , aber alles , was ich bin konzentriert um überwiegend mit einem Fokus auf C ++ 's - Typ - System und auch in Bezug auf RAII. Einer der Gründe, warum solche röntgenbasierten Bytekopien
memcpy
oderqsort
Funktionstypen in C eine geringere praktische Gefahr darstellen, besteht darin, dass die Zerstörung vonf1
undf2
darüber explizit erfolgt (wenn sie sogar eine nicht-triviale Zerstörung erfordern), während Destruktoren ins Bild rücken werden sie implizit und automatisiert (oft mit großem Wert für die Entwickler). Das ist nicht zu erwähnen sogar Staat wie vptrs versteckt und so weiter , die solche Funktionen direkt über planieren würden. Wennf1
besitzt Zeiger undf2
seichtes kopiert sie in einem temporären Kontext, dann stellt es kein Problem, wenn wir versuchen, nicht explizit ein zweites Mal diejenigen besitzen Zeiger zu befreien. In C ++ ist dies etwas, was der Compiler automatisch tun möchte.Und das wird in der Regel größer, wenn in C " Wenn Foo über eigene Zeiger verfügt", da die bei der Ressourcenverwaltung erforderliche Explizite häufig dazu führt, dass etwas in der Regel schwerer zu übersehen ist, während in C ++ ein UDT nicht mehr trivial ist Konstruierbar / zerstörbar, indem nur eine Elementvariable gespeichert wird, die nicht einfach konstruierbar / zerstörbar ist (auf eine Art und Weise, die im Allgemeinen wiederum sehr hilfreich ist, aber nicht, wenn wir versucht sind, Funktionen wie
memcpy
oder zu verwendenrealloc
).Mein Hauptziel ist es nicht, zu versuchen, irgendeinen Nutzen aus dieser Aussage zu ziehen (ich würde sagen, wenn es welche gibt, werden sie fast immer durch die Nachteile der damit verbundenen erhöhten Wahrscheinlichkeit menschlicher Fehler belastet), sondern nur, dies zu sagen funktioniert wie
memcpy
undmemmove
undqsort
undmemset
undrealloc
und so weiter haben keinen Platz in einer Sprache mit UDTs, die so reich an Funktionen und Fähigkeiten sind wie C ++. Ich denke, es wäre nicht zu bestreiten, zu behaupten, dass die überwiegende Mehrheit der C ++ - Entwickler klug wäre, Funktionen wie die Pest zu vermeiden, obwohl dies in C sehr alltägliche Funktionen sind. ' d argumentiert, dass sie weniger Probleme in C aus dem einfachen Grunde darstellen, dass seine Art System viel mehr grundlegenden und vielleicht „stumme“. Das Röntgen von C-Typen und deren Behandlung als Bits und Bytes ist fehleranfällig. Das in C ++ zu tun, ist wohl völlig falsch, weil solche Funktionen gegen sehr grundlegende Merkmale der Sprache und das, was sie vom Typensystem fördert, ankämpfen.Das ist jedoch für mich der größte Reiz von C, insbesondere in Bezug auf die Interoperabilität von Sprachen. Es wäre viel, viel schwieriger, so etwas wie C # 's FFI dazu zu bringen, das vollständige Typsystem und die Sprachfunktionen von C ++ zu verstehen, bis hin zu Konstruktoren, Destruktoren, Ausnahmen, virtuellen Funktionen, Funktions- / Methodenüberladung, Operatorüberladung und all den verschiedenen Arten von Vererbung usw. Bei C handelt es sich um eine relativ langweilige Sprache, die in Bezug auf APIs zum Standard geworden ist, da viele verschiedene Sprachen direkt über FFIs oder indirekt über einige C-API-Exportfunktionen in einer gewünschten Form (z. B. Java Native Interface) importiert werden können ). Und das ist, wo ich meistens links bin keine andere Wahl hat, aber C zu verwenden, da diese Sprache Interoperabilität eine praktische Anforderung in unserem Fall ist (obwohl ich oft‘
Aber weißt du, ich bin ein Pragmatiker (oder zumindest bemühe ich mich, es zu sein). Wenn C das Foul und godawful war, fehleranfällig, böse Sprache einige meiner C ++ Enthusiasten Kollegen behauptet, es zu sein (und ich würde mich für einen C ++ Enthusiasten, außer dass irgendwie hat es nicht auf meinen Teil zu einem Hass auf C führen , im Gegenteil in ihrer eigenen Beziehung und Unterschiede), dann würde ich erwarten, dass zu zeigen, bis in der realen Welt in Form von einigen der buggiest und leakiest hatte es auf mich den gegenteiligen Effekt macht mich beide Sprachen besser zu schätzen wissen und unzuverlässige Produkte und Bibliotheken, die in C geschrieben sind. Und das finde ich nicht. Ich mag Linux, ich wie Apache, Lua, zlib, finde ich OpenGL erträglich für seine lange Tradition gegen eine solche Verschiebung Hardware-Anforderungen, Gimp, libpng, Kairo, usw. Zumindest was Hürden die Sprach Posen scheinen nicht Sackgassen zu stellen, soweit einige coolen Bibliotheken und Produkte in kompetenten Händen zu schreiben, und das ist wirklich alles mir interessieren. So habe ich noch nie der Typ so interessiert in den leidenschaftlichsten gewesen Sprache Kriege, es sei denn, eine pragmatische Berufung zu machen und sagen: „Hey, es gibt coole Sachen da draußen! Lasst uns lernen, wie sie es gemacht und vielleicht gibt es kühle Unterricht, nicht so spezifisch auf die idiomatischen Natur der Sprache, die wir zurückbringen kann für welche Sprache (n) wir auch immer verwenden. " :-D
quelle
memcpy(&f2, f1, sizeof f2);
ist auch "Höllenfeuer herrschende Verwüstung" in C, wennFoo
es irgendwelche Zeiger gibt, oder ist sogar noch schlimmer, da Ihnen auch die Werkzeuge fehlen, um damit umzugehen. So können die Leute C Schreiben nicht tun , Dinge wie , dass so vielFoo
können Instanzen nun wollen die dynamische Array zerstören oder einen Vektor, oder etwas zu diesem Effekt. In einigen besonderen Fällen finde ich häufig, dass es hilfreich ist, bestimmte Datenstrukturen zu schreiben, um sich auf die Tatsache zu stützen, dass die Zerstörung explizit und nicht implizit ist.Foo
wir, wenn wir Zeiger besitzen, eine korrekte Kopie / Verschiebung von ctor, dtor, Verwendung von Wertsemantik usw. vornehmen und viel umfangreicheren und sichereren Code haben könnten. Aber gelegentlich greife ich nach C, wenn ich eine Datenstruktur oder einen Allokator auf der homogenen Ebene von Bits und Bytes verallgemeinern möchte, wobei ich bestimmte Annahmen treffen kann, welche Typen in ihren engen Anwendungsfällen zu einer Vereinfachung neigen Ein bisschen durch solche Annahmen fühle ich mich ein bisschen sicherer in C.API void filter_image(byte* pixels, int w, int h);
Beispiel ein einfaches Beispiel, anstatt wieAPI void filter_image(ImageInterface& img);
(was unseren Code an eine solche Bildschnittstelle koppeln würde). Einschränkung der Anwendbarkeit). In solchen Fällen implementiere ich manchmal nur solche Funktionen in C, da in C ++ wenig zu gewinnen ist und dies die Wahrscheinlichkeit verringert, dass ein solcher Code zukünftige Änderungen benötigt.