Angenommen, ich kann C ++ nur in der Umgebung des Projekts verwenden. Ist es sinnvoll, die Verwendung einiger Sprachfunktionen zu verhindern, die in C ++ enthalten sind, in Java jedoch nicht (z. B. Mehrfachvererbung, Überladung von Operatoren)?
Ich denke die Gründe sind:
- Da Java neuer als C ++ ist, bedeutet dies, dass das Feature nicht gut ist, wenn Java kein Feature von C ++ bereitstellt. Daher sollten wir es vermeiden, es zu verwenden.
- 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.
- Möglicherweise werden Sie eines Tages aufgefordert, den Code in Java zu konvertieren
- Code ohne C ++ - spezifische Funktionen kann normalerweise besser gewartet werden
- 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.
Ist das wahr?
java
c++
code-quality
ggrr
quelle
quelle
volatile
, keinen Zugriff für paketprivate Klassenmitglieder, keine Reflektion / Introspektion, keine Endsperren , keine überprüften Ausnahmen usw.? Die ganze Frage ergibt nicht viel Sinn ... C ++ und Java sind sich oberflächlich ähnlich, aber letztendlich sehr unterschiedliche Sprachen.SomeObject a = previousObject;
macht ganz andere Dinge in Java und C ++. In Java wird eine Referenz kopiert, während in C ++ das Objekt kopiert wird. In Java wirken sich Änderungen ana
auch auf das vorherige Objekt aus. In C ++ haben Sie zwei separate Objekte.Antworten:
Nein, das ist traurig und furchtbar fehlgeleitet.
quelle
operator<<( ostream &, T const & )
wird in der Regel über implementiertfriend
. Das ist das Problem mit pauschalen Aussagen darüber, was eine gute und was eine schlechte Sprache ist: Sie sind gute Ratschläge, außer wenn sie nicht ...Nur weil die Syntax auf der Oberfläche ähnlich zu sein scheint, bedeutet dies nicht, dass die beiden Sprachen kompatibel sind.
1, 4 und 5 sind wirklich die gleiche Frage:
Jetzt bin ich kein Fan von C ++, aber zu sagen, dass "Code ohne C ++ - spezifische Funktionen normalerweise besser zu warten ist", ist einfach lächerlich - glauben Sie wirklich, dass Java alles richtig gemacht und alle guten Funktionen übernommen hat, während es alle schlechten ignoriert hat? Glauben Sie wirklich, dass es etwas gibt, das allgemein als "schlecht" oder "gut" zu bezeichnen ist? Wenn ja, warum haben wir dann nicht eine Sprache, die rein gut ist? Und nein, Java ist sicherlich nicht diese Sprache. Bedeutet das, dass Java und C ++ unbrauchbar sind? Natürlich nicht.
Was ist, wenn Ihre Führungskräfte entscheiden, dass Sie auf C # anstatt auf Java portieren? Nicht nur , dass C # Unterstützung zwingende Betreiber, aber es ist auch der Standard - wenn Sie vorhaben , Menschen zu verlangen , zB verwenden
obj.Equals(obj2)
stattobj == obj2
, die Menschen gehen , Fehler machen die ganze Zeit. Auch wenn man sich nur an die Gemeinsamkeiten der beiden Sprachen hält, gibt es unterschiedliche Erwartungen , eine unterschiedliche Kultur. Wenn Sie so etwas wieif (myField == null)
in C ++ machen, werden die Leute sehen, dass Sie sofort ein Anfänger sind. Wenn Sieif (null == myField)
in C # verwenden, werden die Leute feststellen, dass Sie noch nicht wirklich C # -nativ sind - die Gründe, aus denen C-Entwickler gelernt haben, die "gespiegelte" Variante zu verwenden, gibt es in C # nicht mehr.Nach Ihrer Logik hätten wir uns an Maschinencode, Assembly oder COBOL halten sollen, denn warum sollten wir jemals zu Pascal wechseln, wenn es nur neue Funktionen hinzufügt, die Ihre Programmierer lernen müssen? Warum sollten wir jemals so etwas wie SQL verwenden, wenn es nicht einmal Schleifen hat ? Warum würden wir jemals etwas anderes als SQL verwenden, wenn SQL keine Schleifen hat und X dies tut?
C ++ - Code kann von Java-Programmierern mit Sicherheit nicht verwaltet werden. Ich kann nicht verstehen, woher Sie diese Idee haben - was genau bleibt, wenn Sie C ++ nur auf die Funktionen beschränken, die genauso funktionieren wie in Java? Sie werden nicht einmal Methodenaufrufe bekommen - nicht einmal Funktionsaufrufe . Nur weil beide Sprachen geschweifte Klammern verwenden, bedeutet dies nicht, dass die Sprachen in irgendeiner Weise austauschbar sind.
Das Konvertieren von Java-ähnlichem C ++ - Code ist extrem fehleranfällig, egal was Sie tun. Es gibt einfach zu viele Unterschiede. Wenn Sie möchten, dass Ihre Anwendung in einer anderen Sprache geschrieben wird, überlegen Sie sich, wie Sie alles modularisieren können, damit Sie die Teile austauschen können, ohne das Ganze zu beschädigen. Aber am Ende, YAGNI - egal was Sie tun, es wird einen erheblichen Aufwand bedeuten, Ihren Code "bereit für die Konvertierung nach Java" zu machen. Diese Zeit wird sehr wahrscheinlich besser für das Hinzufügen oder Verbessern Ihrer Funktionen aufgewendet.
Wir verwenden verschiedene Sprachen, weil sie uns verschiedene Werkzeuge zur Lösung von Problemen bieten. Wenn Sie ausführbare Dateien benötigen, die "überall" funktionieren, entscheiden Sie sich für Java. Wenn Sie Code möchten, der "überall" kompiliert , funktioniert C ++ einwandfrei. Wenn Sie Code möchten, der einfach zu verstehen und zu analysieren ist, entscheiden Sie sich für LISP oder was auch immer. Aber eines kann ich Ihnen sagen: Das Schreiben von Code in einer Sprache, als ob Sie ihn in einer anderen schreiben würden, ist immer ein Fehler, und Sie werden darunter leiden. Ganz zu schweigen davon, dass, wenn Sie tatsächlich einen C ++ - Mitarbeiter einstellen, dieser in der Sekunde ausgeführt wird, in der er den "Java-kompatiblen" Code sieht. Und ... der Java-Typ wird dasselbe tun. Weißt du, selbst wenn ich sowohl C ++ als auch Java "kenne", würde ich wie die Hölle rennen :)
Ich musste tatsächlich an (einfachem) C-Code arbeiten, der von einem Pascal-Entwickler geschrieben wurde, der so zu denken schien wie Sie. Er verwendete
#define
s, um C neu zu definieren, damit es mehr wie Pascal aussieht und sich so anfühlt, zusammen mit Dingen wie "BEGIN translates to {". Das Ergebnis war ziemlich vorhersehbar - Code, den weder C noch Pascal-Entwickler verstehen können, und voller Fehler, die auf die undichte "Abstraktion" von Pascal auf C zurückzuführen sind. Und Pascal und C sind aus heutiger Sicht fast identisch . Sogar C <-> C ++ ist ein viel größerer Unterschied, und das sind immer noch Peanuts für etwas wie C ++ <-> Java.quelle
myFunc()
gegenüber(myFunc)
), und das hat einen sehr guten Grund. LISP-basierte Sprachen sind nach wie vor sehr beliebt, insbesondere bei Mathematikern und Physikern. Die Hauptsache ist, dass LISPy-Sprachen modernen C-Programmierern sehr unbekannt sind - aber das ist kaum ein Grund, es zu ignorieren. Schema, Clojure und in gewissem Maße die ML-basierten Sprachen (OCaml, F # ...) sind in der Tat sehr LISPy.if (myField == null)
wieif (myField = null)
, die gerade fein C kompilieren / C ++, aber wahrscheinlich nicht tun , was Sie wollten. Auf der anderen Seiteif (null = myField)
wird ein Fehler ausgelöst, da Sie keine Konstante zuweisen können.Ich werde Ihre Fragen der Reihe nach beantworten.
Ja, jede Funktion, die in Java nicht vorhanden ist, ist ein Horror auf der Festplatte. Es muss von Ihrer Codebasis gebrannt werden. Diejenigen, die nicht gehorchen, werden geschnappt, ihre Seelen werden benutzt, um die RAID-Götter zu besänftigen.
Wenn Sie Zweifel haben, schreiben Sie den Code für das am wenigsten kompetente Mitglied Ihres Teams. Code wird weitaus häufiger gelesen als geschrieben, und Code, der so clever wie möglich ist, ist zu clever zum Lesen. Code-Überprüfungen, die Ihre Mitarbeiter an der Rezeption nicht verstehen, sollten abgelehnt werden. Bringen Sie ihnen bei, wie sie am Wochenende in Visual Basic 2.0 programmieren, und emulieren Sie dann ihren Codierungsstil in der von Ihnen verwendeten Sprache.
Wahr! Aber warum bei Java aufhören? Sie werden möglicherweise gebeten, den Code eines Tages in Basic, Assembler und / oder Perl umzuwandeln. Da es in jeder Sprache Perl-Interpreter gibt, schreiben Sie Ihr Programm einfach als langen Perl-String und führen Sie die Argumente in der Sprache Ihrer Wahl an.
Wenn Sie nun die Sprache ändern müssen, schreiben Sie einfach den Code um, der die Perl-Zeichenfolge umschließt.
Es ist wahr, dass Code, der weniger Funktionen verwendet, einfacher zu warten ist. Und da alle Sprachen einer Turing-Maschine entsprechen und eine Turing-Maschine die wenigsten Funktionen einer Programmiersprache aufweist, muss der oben genannte Perl-Interpreter tatsächlich eine Turing-Maschine (Band und alles) ausführen, die Ihr Problem löst.
Die sprachspezifischen Funktionen von C ++ haben tatsächlich einen wertvollen Nutzen. Da es sich nicht um Java handelt, handelt es sich um Anathema, und diejenigen, die es verwenden, können als Ketzer bezeichnet werden. Wenn C ++ diese Sprachfunktionen nicht hätte, könnten Sie die nicht finden, die Sie opfern müssen. C ++ Sprachfunktionen lösen Probleme!
Schauen Sie, C ++ und Java haben unterschiedliche Fähigkeiten. Das Programmieren im Schnittpunkt von C ++ und Java führt zu Code, der die meisten Vorteile beider Sprachen zunichte gemacht hat.
Java wurde teilweise als Reaktion auf den Missbrauch von C ++ - Funktionen entwickelt. Dies bedeutet nicht, dass die Reaktion gerechtfertigt war, insbesondere Jahre später, wenn die Merkmale gereift sind.
Sie können schreckliche Dinge tun, indem Sie den Operator überladen. Aber keine Sprache kann verhindern, dass schrecklicher Code in der Sprache geschrieben wird, es sei denn, sie verhindert, dass der gesamte Code in der Sprache geschrieben wird.
Und Sie können auch sehr elegante Dinge mit Überladung des Operators tun. Einfache Dinge, wie eine komplexe Zahl oder eine Matrixklasse, die wie eine komplexe Zahl oder eine Matrix funktioniert.
Vorsicht bei der Verwendung von C ++ - Funktionen, die in Java nicht verfügbar sind, ist geboten. Nur weil Ihre aktuelle Gruppe von Entwicklern mit ihrem aktuellen Kenntnisstand ein Feature nicht versteht, bedeutet dies nicht, dass es niemals verwendet werden sollte. Nur weil Sie eine Funktion verwenden können, heißt das noch lange nicht, dass Sie dies tun sollten. In einem Java-starken Geschäft ist die Wahrscheinlichkeit jedoch größer, dass der Widerstand gegen nicht Java-ähnliche Funktionen größer ist als er sein sollte.
Die Konvertierung von Code zwischen Sprachen erfolgt am besten mit einem Umschreiben, egal wie strukturell ähnlich sie sind. Jeder Versuch, dies ohne ein solches Umschreiben zu tun, wird kläglich scheitern.
Viele C ++ - spezifische Funktionen sind Wunder für die Wartung. Mit der Option "Typ löschen" (like
std::function
) können Sie Hierarchien entkoppeln, wodurch Abhängigkeiten verringert werden. Intelligente Zeiger und deterministische Lebensdauern sowie RAII reduzieren die Laufzeitüberraschungen und schieben die Ressourcenkessel aus dem Weg. Schwerwiegende statische Typprüfungen bedeuten, dass der Code nicht kompiliert werden kann, anstatt zu funktionieren. Mix-Ins reduzieren die Codeduplizierung. ADL ermöglicht die ad-hoc-unabhängige Erweiterung von Schnittstellen zwischen Typhierarchien. Mit Lambda können Sie Code an der Stelle schreiben, an der er verwendet wird. Durch Weiterleiten und Verschieben werden Kopien reduziert und die nebenwirkungsfreie Programmierung wird effizienter. Das Überladen von Operatoren reduziert das Zeilenrauschen und lässt den Code mehr wie die Mathematik aussehen, die er modelliert.Vorsicht vor der Turing Teergrube. Sie können alles in jeder Sprache implementieren (einschließlich einer rohen Turing-Maschine mit Klebeband), aber das bedeutet nicht, dass Sie das sollten . Das Emulieren von C ++ - Funktionen mit Java-ähnlichen Konstrukten in C ++ ist eine schreckliche Idee. es wird zu nicht wartbarem Code führen, den niemand lesen oder verstehen kann.
Sie können sich von Java-Designs inspirieren lassen und diese nach C ++ portieren. Ich bin ein großer Fan von Python-Sprachfunktionen und deren Implementierung in C ++, weil mir die Syntax gefällt. Das bedeutet jedoch nicht, dass ich meine Klassenmethoden als statische Methoden schreibe, die ein explizites Selbst verwenden, und dann einen Wrapper schreibe, der den nicht statischen Methodenaufruf an sie weiterleitet.
Modernes C ++ ist nicht so sehr mit der Sprache vergleichbar, die Java emuliert und verworfen hat. Lassen Sie sich nicht von den Funktionen einer Sprache einschränken. Es gibt keine "eine wahre Sprache". Erfahren Sie mehr über neue Sprachen und deren Funktionen und nehmen Sie deren Besonderheiten auf.
quelle
Ich werde nur Ihre Gründe beantworten:
quelle
delete
.delete
. Soweit ich mich erinnere, war in mindestens einem dieser Fälle auchnew
keine dynamische Zuordnung ( ) erforderlich.make_shared
.Java verfügt über Funktionen, die C ++ nicht bietet, wie beispielsweise einen integrierten, schnellen und zuverlässigen Garbage Collector, eine Objekthierarchie mit nur einem Stamm und eine leistungsstarke Introspektion.
Die anderen Funktionen von Java sind so konzipiert, dass sie mit den exklusiven Funktionen von Java zusammenarbeiten. Viele der C ++ - Funktionen von Java können weggelassen werden, da die neuen Funktionen den Mangel ausgleichen. Beispielsweise verfügt Java nicht über stapelzugeordnete Objekte mit deterministischen Destruktoren, sondern über endgültige Blöcke (und Versuche mit Ressourcen seit Java 7) und den Garbage Collector, um diesen Mangel auszugleichen.
C ++ hat keine endgültigen Blöcke oder Speicherbereinigungen. Wenn Sie keine Destruktoren verwenden, weil sie in Java nicht vorhanden sind (ich zähle keine Finalizer), befinden Sie sich auf der C-Ebene der Ressourcenverwaltung (dh alle manuell), mit der Ausnahme, dass Sie Ihre Bereinigung nicht einmal gruppieren können in einen Bereinigungsblock, zu dem Sie gehen, weil Java auch keinen hat. Denken Sie wirklich, dass dies die Wartbarkeit verbessert?
Java hat eine übergeordnete Objekthierarchie, in der jede Klasse letztendlich von Object abgeleitet ist, und die wenigen primitiven Typen können auch automatisch in solche Klassen eingeschlossen werden. Dies ermöglicht das einmalige Schreiben von Objektcontainern, um Zeiger auf das Objekt zu speichern. Mit Java 5 wurden Generika eingeführt, die die Casts entfernen, die solche Container benötigen, aber dennoch so ziemlich denselben Code kompilieren.
C ++ hat keine solche Hierarchie. Um das Schreiben von Containern zu vereinfachen, die für mehrere Typen funktionieren, verwenden Sie Vorlagen. Hierbei handelt es sich um Entwürfe, die vom Compiler bei Bedarf für verschiedene Typen instanziiert werden. Verbieten Sie die Verwendung von Vorlagen (und Makros) und gehen Sie den C-Weg, entweder denselben Containercode für verschiedene Typen immer wieder zu schreiben oder leere Zeiger zu verwenden? (Warten Sie, Java hat keine leeren Zeiger!) Sind Sie sicher, dass dies die Wartbarkeit erhöhen würde?
Eine anständige Sprache hat eine Vielzahl von Funktionen, die zusammenarbeiten sollen. Indem Sie Features von Sprache A verbieten, weil Sprache B sie nicht hat, lähmen Sie Sprache A, weil Sie nicht gleichzeitig Features von B hinzufügen, die B zu einem zusammenhängenden Ganzen machen.
Das heißt nicht, dass Sie die zulässigen Funktionen von C ++ nicht einschränken dürfen. C ++ ist eine große, historisch gewachsene Sprache, die es dem Programmierer ermöglicht, das zu tun, was er will, und zwar in Bezug auf Sicherheit und Benutzerfreundlichkeit. Nicht alle Funktionen in ihrer ganzen Flexibilität sind erforderlich, um gute Programme zu erstellen. Es gibt viele Codierungsstandards, die die Verwendung einiger Funktionen einschränken. Zum Beispiel verbieten Googles Richtlinien meistens Mehrfachvererbung, komplexe Vorlagen und Ausnahmen (obwohl die letzte aus historischen Gründen ist). Es ist jedoch keine Funktion verboten, "weil Java sie nicht hat". Die Funktionen werden nur im Rahmen von C ++ berücksichtigt.
quelle
Object
ist so ziemlich einvoid*
für die meisten Zwecke - Trotzdem, igitt.finally
ist kein Ersatz für sie. Die beiden Sprachen unterscheiden sich nur grundlegend .Ich habe darüber nachgedacht, ob ich eine weitere Antwort veröffentlichen soll, wenn Sie bereits eine Nummer haben, die völlig vernünftige Schlussfolgerungen zu ziehen scheint: Ihre Idee ist im Grunde eine Katastrophe, die darauf wartet, passiert zu werden. Ich denke jedoch, dass sie einige hochrelevante Gründe für diese Schlussfolgerung nicht aufgezeigt haben.
Die Unterschiede zwischen Java und C ++ gehen weit über die Details hinaus, auf die Sie sich anscheinend konzentriert haben.
Sie sprechen beispielsweise über das Verbot der Mehrfachvererbung in C ++. Zunächst möchte ich darauf hinweisen, dass hier einfach der springende Punkt fehlt. Java definiert "Interfaces" als separate Dinge von "Klassen". Eine Klasse erbt nur von einer anderen Klasse, kann jedoch eine beliebige Anzahl von Schnittstellen implementieren.
C ++ trennt die beiden Konzepte nicht auf diese Weise. Die nächstgelegene analoge C ++ zur Implementierung einer Schnittstelle in Java bietet wird von einer anderen Klasse erben. Aus diesem Grund müssen Sie wahrscheinlich in C ++ Mehrfachvererbung verwenden , um die beiden Elemente im Einklang zu halten. Sie möchten jedoch einige dieser Basisklassen in etwa auf die gleiche Weise einschränken, wie Java eine Schnittstelle im Vergleich zu einer Klasse einschränkt (dh im Wesentlichen dass es Funktionssignaturen spezifiziert, aber zumindest meistens keine Implementierungen).
Das kratzt aber kaum an der Oberfläche der wirklichen Unterschiede zwischen den beiden. In der Realität, wo Java-Code wahrscheinlich Schnittstellen und Klassen definiert, die diese Schnittstellen implementieren, ist es viel wahrscheinlicher, dass C ++ - Code einige Vorlagen definiert, die mit jeder Klasse funktionieren , die ihre Anforderungen erfüllt (nicht nur mit solchen, die speziell für die Implementierung der Schnittstelle definiert wurden (s) es spezifiziert).
Wenn Sie ehrlich gesagt Code wollen, der im Grunde genommen "Java mit C ++ - Syntax" ist, müssen Sie mit ziemlicher Sicherheit alles verbieten, was dem letzteren ähnlich ist. Sie müssen die Verwendung von Vorlagen auf ungefähr die Ebene "Container of T" beschränken, die von Java-Generika unterstützt wird. Leider führt dies zu einem C ++ - Code, der so durcheinander ist, dass niemand ihn so wie er jetzt existiert warten kann, ganz zu schweigen von der langfristigen Möglichkeit, ihn in eine andere Programmiersprache zu übersetzen.
Wenn Sie wirklich Code möchten, der in Zukunft in eine andere Sprache konvertiert werden kann, bemühen Sie sich, ihn so sauber und lesbar wie möglich zu gestalten. Das Ideal ist, Pseudocode zu schreiben und noch ausführen zu lassen. Gut geschriebene moderne C ++ - Ansätze, die das Ideal viel näher bringen als die von Ihnen vorgeschlagene Teilmenge. Egal wie Sie es schreiben, wenn Sie jemals nach Java übersetzen, müssen Sie tatsächlich den Code übersetzen, nicht nur die Syntax der einzelnen Anweisungen.
quelle
Wenn Sie Code in Sprache X schreiben, nehmen Sie sich Zeit, um die Sprache richtig zu lernen, und nutzen Sie alle Funktionen, die es bietet, um das Problem zu lösen. Schlimme Dinge passieren, wenn Sie versuchen, eine "Wort für Wort" -Übersetzung von einer Sprache in eine andere zu machen, sei es Japanisch in Englisch oder Java in C ++. Es ist weitaus besser, mit einem guten Verständnis des Problems zu beginnen und die Lösung so auszudrücken, wie es für die verwendete Sprache am natürlichsten ist.
Vor Jahren sah ich ein C-Programm ohne Einrückung und jede Anweisung begann in Spalte 7, weil der Autor des Codes ein Fortran-Programmierer war, der zufällig C verwendete. Andere Fortran-Programmierer waren nervös wegen dieser neuartigen Dinge, die Zeiger genannt wurden. Ich hatte nicht das Herz, Zeiger auf Zeiger zu erwähnen, ich glaube, sie wären sofort ohnmächtig geworden.
Stellen Sie sich vor, Sie beauftragen jemanden, der diesen Code in Zukunft verwaltet. Wenn es sich um guten C ++ - Code handelt, können Sie einen kompetenten C ++ - Entwickler einstellen, der sich zurechtfinden sollte. Wenn es sich um "Java in C ++" handelt, können weder C ++ - noch Java-Entwickler den Code leicht verstehen.
quelle
Alle Ihre Gründe können widerlegt werden:
Dies bedeutet nicht, dass die Funktion nicht gut ist (keine Funktion kann von Natur aus schlecht sein). Dies bedeutet nur, dass die Funktion häufig missbraucht wurde (oder aufgrund grundlegender Konzepte wie direkter Zeiger oder Garbage Collection nicht implementiert werden konnte). Java soll per Definition einfacher und programmiererfreundlicher sein, daher sollten Features entfernt werden, die sich als leicht missbräuchlich erwiesen haben.
Oh kann es sein? Sehen wir uns den einfachsten C ++ - Code an:
Hoppla, es werden keine "sprachspezifischen" Funktionen verwendet, aber es ist für Java-Entwickler bereits unerreichbar! Weil Sie in Java mit "." Dereferenzieren während hier ist es "->.
Oder C #. Oder Haskell. Oder Python. Oder Ruby. Oder COBOL (ja, das kannst du!). Wie kannst du die Zukunft erzählen?
Genau das Gegenteil. Alle Funktionen wurden eingeführt, um die Programmierung zu vereinfachen und die Wartung zu vereinfachen. ZB: Nehmen Sie ein Programm, das auf Schwimmern läuft. Rüste es jetzt auf, um komplexe Zahlen zu verarbeiten. Bedienerüberladung zur Rettung!
Aber Java hat mehrere Vererbung! Es heißt "Schnittstelle". Die Java-Implementierung ist eine problematische Problemumgehung, um den gefürchteten Diamanten zu vermeiden, der dadurch entsteht, dass alles davon abgeleitet ist
Object
. Es wird eingeführt,interface
welcher einzige Zweck darin besteht, etwas zu sein, von dem nicht abgeleitet wirdObject
. C ++ hatte dieses Problem nie - es gibt keine verbindliche gemeinsame Basis, sodass jede Klasse als Schnittstelle ohne den gefürchteten Diamanten fungieren kann.Randnotiz: Java hat kürzlich ... konkrete Methoden in Interfaces eingeführt. Es wurde eine Funktion hinzugefügt, mit der C ++ immer ein Problem lösen musste, das es nie gab.
Sie haben auch nur sehr wenige "Dinge erwähnt, die C ++ hat, Java jedoch nicht". Einer der größten Unterschiede zwischen C ++ und Java ist die Kontrolle über das Speicherlayout. Sie können ein Array von Zeigern auf Objekte erstellen (genau wie in Java) ODER einen zusammenhängenden Speicherblock erstellen. Wenn ich mir jetzt Gedanken über eine C ++ - Funktion machen würde, die Java-Entwickler irreführen könnte, wäre etwas so Verborgenes und Feines wie dieses auf meiner Liste viel höher als offensichtlich und auf den ersten Blick erkennbar, z. B. mehrfache Vererbung oder überladene Operatoren.
Fazit: Clean Code ist Clean Code. Java oder C ++ - gleicher Unterschied. Halte es einfach. Unnötige Komplikationen sind die häufigste Ursache für fehlerhaften Code.
quelle
Nein, Sie sollten im Allgemeinen nicht C ++ schreiben, als wäre es Java, und Sie sollten auf keinen Fall C ++ - Sprachfunktionen auslassen, die in Java nicht vorhanden sind.
Zum einen handelt es sich bei Java um Garbage Collected, und daher gibt es kein Äquivalent zum C ++ - Schlüsselwort "delete". Okay, Sie implementieren ein Programm, ohne es zu löschen, da dies nach Ihren Regeln nicht zulässig ist.
Herzlichen Glückwunsch, Sie haben jetzt ein Speicherleck;). Das ist auch nicht theoretisch - genau das habe ich in einem Open-Source-Spiel gesehen.
In ähnlicher Weise hat Java keine ähnlichen C ++ - Zeiger wie Java, wodurch viele gängige Funktionsaufrufkonventionen ausgeschlossen werden.
Es gibt Funktionen in C ++, die Sie vielleicht vermeiden sollten (siehe unten), aber "nicht in Java zu sein" ist kein guter Lackmustest.
Bessere Richtlinien wären:
Punkt (3) bedeutet, dass Sie keinen Java-Programmierer-Code in C ++ haben sollten, ohne diese in C ++ zu trainieren. Es gibt einige subtile, aber sehr wichtige Unterschiede, die sie möglicherweise nicht lernen, wenn sie versuchen, sie wie einen seltsamen Java-Dialekt zu behandeln.
Punkt (2) bedeutet, dass es möglicherweise am besten ist, diese alternative Lösung zu verwenden , wenn sich Ihr Team speziell mit Mehrfachvererbung unwohl fühlt (z. B.) und wenn es eine geeignete Lösung gibt, die diese nicht verwendet. Dies hängt jedoch speziell von Ihrem Team ab. Wenn sich Ihr Team dagegen mit dieser alternativen Lösung unwohl fühlt als mit der Mehrfachvererbung, verwenden Sie die Mehrfachvererbung!
Schließlich gibt es Sprachfunktionen von C ++, die man wohl vermeiden sollte. Wenn Sie wissen möchten, was das ist, fragen Sie C ++ - Programmierer , anstatt Programmierer einer anderen Sprache. Einige Beispiele sind Zeigerarithmetik (kein universeller Konsens) und goto.
quelle
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.
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.
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: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: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: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 MethodeFoo::reset(void)
existiert, ein unachtsamer Entwickler könnten versuchen , es mit zu nennenfoo.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 machenfoo
, 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.
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:
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!).
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
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:
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 , dassconstexpr
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 ++,quelle
import SomeVeryBasicPackage
und tun dies einfach ?". Stellen Sie eine erweiterte Frage und die erste Antwort ist fast zwangsläufig entlang der Linien von „Warum haben Sie nichtimport SomeMagicalPackage
und nur tun , dass ?“Nein.
Wenn Sie "aufgrund der Umgebung des Projekts" nur C ++ verwenden, gibt es, wenn überhaupt, kaum einen Grund, überhaupt über eine andere Technologie nachzudenken , ganz gleich, wie sehr Sie sie persönlich bevorzugen / hoffen, sie zu verwenden / zu evangelisieren.
Ob "Technologie X" oder "Y" ein bestimmtes Feature unterstützt, sollte sich nicht auf die Art und Weise auswirken , in der Sie Ihre C ++ - Anwendung erstellen.
Es ist eine C ++ - Anwendung, vermutlich aus irgendeinem "guten Grund" (jetzt oder in der Vergangenheit), also sollten Sie sie als C ++ - Anwendung schreiben , wobei Sie das verwenden, was auch immer diese spezielle "Toolbox" bietet.
Wenn die Anwendung auf eine andere Technologie portiert werden muss (und nur dann), sollten Sie Funktionen auf anderen Plattformen in Betracht ziehen. Es gibt keinen Punkt „cutting off Nase trotz deines Gesichts“ auf der off-Chance , dass etwas könnte passieren. Denken Sie jedoch daran, dass das Umschreiben im Großhandel eine teure und riskante Angelegenheit ist, die das Management wahrscheinlich nicht ohne einen guten Grund übernehmen wird.
Vor einigen Jahren gab es eine ähnliche Debatte ("zu verwenden oder nicht zu verwenden") in der Visual Basic [.Net] -Welt, in der jemand die gute Idee hatte, dass Sie Visual Basic-Anwendungen schreiben sollten, ohne eine der [Kernsprachen] zu verwenden. Funktionalität, die vom Microsoft.VisualBasic-Namespace bereitgestellt wird. Es wäre, als würde man versuchen, eine C ++ - Anwendung ohne den Namespace std :: zu schreiben. OK, es ist möglich, aber warum sollte sich irgendjemand, der bei klarem Verstand ist, die Mühe machen, dies zu tun?
quelle
Microsoft.VisualBasic
Namespace-Ding ist ein bisschen langweilig. Es ist viele Jahre her, dass ich es das letzte Mal benutzt habe, aber zumindest zu Beginn war es hauptsächlich darauf ausgerichtet, die Abwärtskompatibilität mit VB6 zu gewährleisten (und / oder VB6-Programmierern das Gefühl zu geben, "zu Hause" zu sein). Es stellte hauptsächlich Funktionen bereit, die bereits im Rest des Frameworks in einer moderneren (und besser integrierten) Form verfügbar waren, sodass es in neuen Projekten selten Sinn machte, sie zu verwenden. Im Gegensatz dazu befindet sich imstd::
Namespace die gesamte Standardbibliothek. Wenn Sie dies vermeiden, wird die gesamte BCL in .NET vermieden.Die aktuellen Antworten sagen alle, dass dies eine schlechte Sache ist, da Sie die von Ihnen verwendete Sprache ausnutzen und auch erklären sollten, warum eine C ++ - Funktion nicht "schlecht" ist, nur weil sie nicht in Java enthalten ist. Ich werde dies aus einem anderen Blickwinkel beantworten.
Es ist eine Sache, komplexe C ++ - Funktionen wie Mehrfachvererbung, Überladen von Operatoren und das Definieren einer eigenen Vorlage zu vermeiden.
Aber jedes Problem, das mehr als die einfachste Aufgabe erledigt:
Es gibt keine gemeinsame Untermenge von Java und C ++, die das oben Genannte ermöglicht. Daher ist es unmöglich, das zu tun, wonach Sie fragen. (Wenn Sie nach Java und C # fragen, haben Sie eine viel bessere Chance, da beide Garbage Collectors verwenden.)
Sie könnten jedoch verlangen, dass der Code so geschrieben wird, dass ein Java-Entwickler verstehen kann, was zu tun ist (aber nicht das detaillierte "Wie"), und dies wäre sinnvoll.
Sie können auch Ihre eigene Sprache entwerfen, die Sie sowohl in C ++ als auch in JAVA implementiert haben.
quelle
Niemand sollte Code schreiben, den andere Programmierer nicht verstehen. Wenn Sie der Meinung sind, dass die Sprachsperre ein Problem darstellt, warten Sie, bis Sie die Entwicklersperre aktiviert haben. Einer hält dich eher als Geisel als der andere.
Es gibt wirklich keine technischen Gründe. Was Sie erstellt haben, ist ein Szenario, in dem eine Sprache aus irgendeinem Grund verwendet wurde, aber viele aktuelle und möglicherweise zukünftige Entwickler es nicht wirklich verstehen.
Ich vermute, Java-Entwickler schreiben C ++ wahrscheinlich so, wie sie es in Java schreiben. Warum also eine Regel? Möglicherweise entdecken Sie einige C ++ - spezifische Funktionen, die mit ein wenig C ++ - Anleitung / Dokumentation für Ihre Java-Entwickler einfacher zu implementieren und zu warten sind, als die große Menge an Java-Chaos, mit dem sie sonst zu kämpfen hätten.
Dies war ein Argument für die Probleme von BASIC-Programmierern, die auf objektorientierte Sprachen umsteigen. Es ist nicht so, dass sie OOP-Praktiken zum Nachteil neuer Entwickler implementieren, die sie nicht verstehen, sondern dass sie sie überhaupt nicht implementieren. Wenn sie das tun, verstehen sie es normalerweise falsch. Wenn etwas schlecht gemacht wird, muss es unabhängig vom Grund entfernt werden.
Abgesehen davon, dass jemand Code blind kopiert und einfügt, wird er dies in vielen Bereichen tun, die er sowieso nicht versteht.
quelle