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:
lock_mutex(&mutex);
// call some functions
...
unlock_mutex(&mutex);
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:
void f(const Foo* f1)
{
Foo f2;
memcpy(&f2, f1, sizeof f2);
...
}
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 wie memset
, 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):
memcpy(&f2, f1, sizeof f2);
ist auch "Höllenfeuer herrschende Verwüstung" in C, wenn Foo irgendwelche Zeiger besitzt, oder ist noch schlimmer, da Ihnen auch die Werkzeuge fehlen, um damit umzugehen.
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
oder qsort
Funktionstypen in C eine geringere praktische Gefahr darstellen, besteht darin, dass die Zerstörung von f1
und f2
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. Wenn f1
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 verwenden realloc
).
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
und memmove
und qsort
und memset
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