Es gibt bereits einige gute Punkte in anderen Antworten, aber ich möchte eine vollständigere Antwort geben und Ihre Fragen und Aussagen einzeln beantworten.
Wenn Java keine Funktion von C ++ bereitstellt, bedeutet dies, dass die Funktion nicht gut ist. Daher sollten wir die Verwendung dieser Funktion verhindern.
Dies wurde ziemlich gut beantwortet: Java ist nicht "der gute Teil" von C ++, und es gibt auch keinen Grund, dies zu glauben.
Insbesondere, obwohl die Vorzüge jedes einzelnen C ++ - Features umstritten sind, sind viele der Features von C ++ 11 / C ++ 14, die nicht Teil von Java sind, nicht unbedingt ausgeschlossen, da die Java-Designer sie für eine schlechte Idee hielten. Als Beispiel hatte Java bis zur Version 8 keine Lambdas, aber sie wurden in C ++ im C ++ 11-Standard eingeführt. Vor Java 8 hätte Ihre Annahme, dass in Java fehlende C ++ - Features aufgrund ihrer "Nicht-Gut" -Funktion nicht vorhanden waren, impliziert, dass Lambdas als Sprachfeature "Nicht-Gut" sind (zum Schrecken der LISPer überall, auch wenn sie nicht gut sind) wahrscheinlich entsetzt genug, um zu hören, dass Sie Java anscheinend tatsächlich mögen ). Aber jetzt haben die Java-Designer Lambdas mit ihrem Gütesiegel versehen, und jetzt sind sie eine gute Sache.
Um auch in Java 8 ein wenig tiefer zu gehen, sind Lambdas-as-Closures nicht so flexibel wie die Lambdas von C ++ 14, aber dies kann eher an den Einschränkungen der JVM-Architektur liegen, als an der bewussten Entscheidung, dass der flexiblere Ansatz von a schlecht ist Perspektive des Sprachdesigns.
C ++ - Code mit C ++ - spezifischen Funktionen (z. B. Friend-Funktionen, Mehrfachvererbung) kann nur von C ++ - Programmierern gepflegt oder überprüft werden. Wenn wir jedoch nur C ++ wie Java schreiben (ohne C ++ - sprachspezifische Funktion), kann der Code von beiden gepflegt oder überprüft werden C ++ und Java Programmierer.
Dies ist die Hauptsache, auf die ich antworten wollte.
Generell kann es sinnvoll sein, Code-Reviews von Programmierern zu erhalten, die mit der von Ihnen verwendeten Sprache nicht vertraut sind. Sie können Ihnen wertvolle Rückmeldungen über die Klarheit Ihrer Funktions- / Methodennamen und Kommentare geben. Wenn die Sprache einer oder mehreren bereits bekannten Sprachen ähnlich ist, kann sie möglicherweise dem grundlegenden Programmablauf folgen und möglicherweise logische Fehler abfangen.
Es ist jedoch nicht der Fall, dass diese Art der Überprüfung jemals "so gut wie" oder "gleichwertig" mit der Überprüfung von Entwicklern ist, die die von Ihnen verwendete Sprache tatsächlich kennen. Dies liegt im Wesentlichen daran, dass das Aussehen einer Sprache in der Regel geringfügige Unterschiede verdeckt, während das Verhalten einer Sprache (insbesondere im Fall von C ++ und Java) für die Sprache möglicherweise nicht idiomatisch und / oder immer noch zu verwirrend ist für die Rezensenten.
Lassen Sie uns zunächst überlegen, was es bedeuten würde, C ++ so zu gestalten, dass es wie Java aussieht. Im einfachen Fall können Sie new
Objekte wie in Java instanziieren:
Foo foo = new Foo();
Aber Objekte instanziiert diese Weise Verwendung ->
anstelle von .
Methoden aufrufen, wenn Sie also Methode wollen ruft wie Java zu suchen, müssen Sie stattdessen schreiben:
Foo& foo = *new Foo();
Aber das ist nicht idiomatisch; Insbesondere muss der Speicher später mit bereinigt werden delete &foo
, was einige erfahrene C ++ - Entwickler möglicherweise nicht einmal als gültigen Code erkennen . In beiden Fällen gibt es lustige Nicht-Java-ähnliche Symbole gänzlich besprüht, so dass wir nicht ganz die Sprache Java „aussehen“ machen. (Sie könnten die *new
Verwendung von #define New *new
oder, schlimmer noch, eliminieren #define new *new
, aber dann bitten Sie nur Ihre Mitentwickler, Sie zu hassen.) Und, wie oben erwähnt, delete
gibt es in Java auf keinen Fall (wie in einer anderen Antwort erwähnt) ) Sie können die Objektnutzung niemals so aussehen lassen wie in Java, ohne dass Speicherlecks auftreten.
Modernes C ++ enthält jedoch intelligente gemeinsame Zeiger, die sich stark wie die speicherverwalteten Variablenreferenzen von Java verhalten. Überall in Java, wo Sie schreiben könnten Foo foo = new Foo();
, könnten Sie stattdessen schreiben:
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
Jetzt verwenden Sie eine Sprachfunktion, die Java unter der Haube sehr ähnelt. Aber plötzlich müssen Sie Nicht-C ++ - Rezensenten eine Menge erklären: Was ist das für ein shared_ptr
Zeug? Was sind die subtilen kniffligen "Fallstricke" make_shared
? (Es wird die perfekte Weiterleitung verwendet, die einige Fehlerfälle aufweist und dazu führen kann, dass der "falsche" Konstruktor aufgerufen wird.) Warum müssen Methoden mit aufgerufen werden ->
, aber die Verwendung .
mit bestimmten Methoden ist vom Compiler zulässig? ( shared_ptr
Hat seine eigenen Methoden.) Wenn die Methode Foo::reset(void)
existiert, ein unachtsamer Entwickler könnten versuchen , es mit zu nennen foo.reset()
, die (wenn es nur einen gemeinsamen Zeiger auf diese Instanz von ist , Foo
wenn der Anruf auftritt) den zugrunde liegenden Speicher löschen und zunichte machen foo
, und Java-Entwickler werden dieses Problem wahrscheinlich nicht bemerken.
Außerdem C ++ hat eine Menge von Gefahren , die spezifisch auf die Sprache. Wie ich am besten beurteilen kann, lernen die meisten C ++ - Entwickler, mit diesen Fallstricken umzugehen, indem sie nach und nach ihre eigene Ausdrucksweise für "sichere" C ++ - Praktiken entwickeln, die für sie oder ihr Entwicklungsteam häufig etwas Besonderes ist (siehe zum Beispiel die vorhandene Antwort, in der das erwähnt wird) Die Codierungspraktiken von Google und der Kommentar dazu lauten: "Erfahrene C ++ - Veteranen lehnen normalerweise die Codierungsrichtlinien von Google ab." Alle Behauptungen, dass die Sprache möglicherweise zu kompliziert ist, scheinen (zumindest nach meiner Erfahrung) in der Regel mit einer Variation von "Nun, hör auf, sie falsch zu verwenden" zu stimmen. Mir ist klar, dass dies eine äußerst negative Sichtweise der C ++ - Community ist, und es gibt sicherlich erfahrene Entwickler, die eher bereit sind, Sprachlernern zu helfen, aber es gibt sie scheint eine gewisse Abwehrbereitschaft gegenüber z. B. undefiniertem Verhalten zu sein (siehe z. B. einen Großteil der Diskussion in meinem Link "Fallstricke" oben).
Java-Entwickler werden einfach nicht hilfreich sein, um diese Fallstricke durch Code-Überprüfung zu finden und zu korrigieren.
Sie werden möglicherweise gebeten, den Code eines Tages nach Java zu konvertieren.
Es ist absolut berechtigt - lobenswert, auch - zu versuchen, zu berücksichtigen, was in Zukunft mit Ihrem Code geschehen könnte, während Sie sich in der Entwurfsphase befinden.
Aber zunächst scheint diese spezielle Überlegung eine entfernte Möglichkeit zu sein: Code wird in der Regel entweder so wie er ist wiederverwendet (zum Beispiel könnten Sie einen Teil oder den gesamten funktionierenden C ++ - Code mithilfe einer JNI-Schnittstelle in eine zukünftige Java-Software einbinden) oder vollständig neu geschrieben als direkt manuell "transkribiert".
Und zweitens sagen Sie später:
Für jede sprachspezifische C ++ - Funktion (z. B. Mehrfachvererbung) sollten Alternativen in Java implementiert werden.
Dies hebt im Wesentlichen Ihren "In Java konvertieren" -Punkt auf. Wenn Software in idiomatischem C ++ geschrieben und dann in idiomatisches Java konvertiert wird, besteht kein Grund zu der Annahme, dass diese Konvertierung durch eine präzise Eins-zu-Eins-Zuordnung von C ++ - Features zu Java-Features erfolgen würde (oder könnte!).
Code ohne C ++ - spezifische Funktionen kann normalerweise besser gewartet werden.
Es ist nicht klar, was Sie hier meinen, aber ich stimme einem Teil davon zu: Wenn Sie nicht sehr vorsichtig sind und selbst wenn Sie vorsichtig sind, können C ++ - Funktionen zu Problemen mit der Wartbarkeit führen. Die C ++ FQA Lite (eine Website, die kritisch gegenüber der Sprache und ihren Anhängern ist und zumindest so aussieht, als würde sie diese Sprache ziemlich gut verstehen) gibt dies an
... 80% der Entwickler verstehen höchstens 20% der Sprache. Es ist nicht dasselbe 20% für verschiedene Leute, also rechnen Sie nicht damit, dass sie den Code des anderen verstehen.
BITTE BEACHTEN SIE: Wenn Sie ein C ++ - Fan sind und in meiner Antwort auf diesen Punkt eingehen, sind Sie geneigt, zu den Kommentaren zu springen, um zu argumentieren, dass der Autor der FQA C ++ nicht wirklich versteht oder in den meisten seiner Argumente unaufrichtig ist Beachten Sie, dass (1) genau zwei Sätze, nachdem ich ihn zitiere, ich anerkenne, dass die FQA eine sehr voreingenommene Quelle ist, und (2) es ist nicht wirklich wichtig, was ich versuche zu sagen, ob der FQA-Autor C ++ versteht oder nicht , und ich versuche nicht, C ++ zu schlagen, und Sie sollten den Rest des Beitrags lesen, ohne davon auszugehen, dass ich Anti-C ++ bin, nur weil ich die FQA zitiert habe. Ende der Notiz.
In ähnlicher Weise hasst Linus Torvalds C ++ im Wesentlichen aus diesem Grund (Warnung: Link beinhaltet viel Fluchen im wahrhaft berüchtigten Linus-Stil).
Offensichtlich sind diese Einstellungen sehr voreingenommen, aber selbst C ++ - Befürworter sagen oft, dass Sie nicht den gesamten Sprachfeaturesatz verwenden sollten (siehe auch die Codierungsrichtlinien von Google; außerdem Bjarne Stroustrup, der Schöpfer von C ++ , hat öffentlich erklärt, "In C ++ gibt es eine viel kleinere und sauberere Sprache, die Schwierigkeiten hat, herauszukommen").
Ich denke, die Idee, dass C ++ - Funktionen möglicherweise zu einfach zu missbrauchen sind, hat einen gewissen Wert, insbesondere wenn Sie aus einem Java-Hintergrund stammen. Darüber hinaus hat die Idee, diese Probleme durch Beschränkung auf eine Teilmenge der Sprache zu lindern, ihre Berechtigung.
Die Entscheidung, welche Teilmenge basierend auf einer anderen Sprache verwendet werden soll , scheint jedoch nicht der richtige Ansatz zu sein, es sei denn, die "andere Sprache" ist C, da es tatsächlich eine C-ähnliche Teilmenge der C ++ - Sprache gibt. (Linus bezieht sich in seiner obigen Randalierung darauf, und Scott Meyers bezeichnet diese Teilmenge sogar als "Teilsprache".) Javas Laufzeitparadigma (mit Speicherbereinigung, ausgeführt auf einer VM) unterscheidet sich grundlegend von C ++ Es ist nicht klar, ob es nützliche Lektionen zur Verwendung von C ++ gibt, und wie oben erwähnt, kann der Versuch, Lektionen über C ++ direkt aus Java zu ziehen, zu einem sehr nicht-idiomatischen Code führen.
Versuchen Sie stattdessen, Ihre "akzeptable Teilmenge" der Sprache zu definieren, um zu verstehen, wie die Sprache idiomatisch verwendet werden kann. Wenn Sie eine ziemlich restriktive Teilmenge wünschen, die noch viele der Funktionen von C ++ nutzt, die über das hinausgehen, was C bietet, ist die oben erwähnte Google Coding-Richtlinie möglicherweise ein guter Ausgangspunkt. Klar, es gibt Entwickler, die sagen, dass es für einige der Einschränkungen von Google kein "rationales Argument" gibt , aber es sei denn, Sie möchten Alexandrescu von seiner Arbeit an der D-Sprache fernhalten (was Ihnen selbst etwas sagen sollte) wahrscheinlich okay Es ist sicherlich besser, als C ++ in Java zu verwandeln.
Ein weiterer guter Ausgangspunkt für eine Reihe von Code-Richtlinien sind die neuen C ++ Core-Richtlinien , die von Bjarne Stroustrup und Herb Sutter in Arbeit sind.
Die einzige andere Möglichkeit, mit den Mängeln von C ++ umzugehen, besteht darin, eine andere Sprache auszuwählen. Es hört sich so an, als ob Sie Java mögen, und Sie glauben, dass dieses Projekt möglicherweise irgendwann in Java konvertiert wird. Wie in einer anderen Antwort erwähnt, können Sie einfach ... mit Java beginnen.
Es gibt zwei Gründe , warum Sie wirklich wirklich vielleicht brauchen etwas anderes als Java zu verwenden:
- Sie brauchen wirklich die Laufzeitleistung. In diesem Fall hilft es Ihnen wahrscheinlich nicht, C ++ wie Java zu behandeln, da Java-ähnliche Techniken wie Shared Pointers Ihre Laufzeitleistung beeinträchtigen.
- Sie benötigen die Software, um auf einer unbekannten Plattform zu arbeiten, die die JVM noch nicht unterstützt. In diesem Fall stecken Sie wahrscheinlich in Sprachen mit GCC- oder Clang-Frontends fest. C und C ++ sind offensichtliche Kandidaten, aber Sie könnten auch etwas wie Rust untersuchen. (Quick Plug: Ich habe Rust nicht in großem Umfang verwendet, aber es sieht großartig aus und ich bin gespannt darauf, so bald wie möglich an einem größeren Rust-Projekt zu arbeiten. Ich denke, jeder, der ein C ++ - Projekt in Betracht zieht, sollte Rust als Alternative in Betracht ziehen.)
Für jede sprachspezifische C ++ - Funktion (z. B. Mehrfachvererbung) sollten Alternativen in Java implementiert werden. Wenn dies nicht der Fall ist, ist das Entwurfsmuster oder die Codearchitektur problematisch.
Ich habe das schon etwas angesprochen, aber ich habe deinen zweiten Satz absichtlich weggelassen.
Ich bin nicht davon überzeugt, dass so etwas constexpr
, was in einer teilweise JIT-fähigen Sprache wie Java keinen Sinn ergibt, ein Hinweis auf eine ungültige Architektur ist. Ich bin offen für die Idee , dass die übermäßige Verwendung von Template - Meta-Programmierung könnte mehr Probleme als es wert ist, vor allem jetzt , dass constexpr
dafür Funktion Auswertung kompilierte Zeit existiert, aber es ist klar , aus dem Fall , constexpr
dass es keine Design - Fehler , wenn Sie Verwenden Sie es: Sie stellen lediglich sicher, dass einige Berechnungen ausgeführt werden, bevor Sie den Code ausführen. Dies ist eine enorme Leistungssteigerung (siehe zum Beispiel diesen Eintrag für das n-body-Problem von The Benchmark Game , das alle anderen Einträge außer einem anderen übertrifft) geschrieben in C ++,