他の回答にはすでにいくつかの良い点がありますが、より完全な回答を提供し、質問や声明を個別に取り上げたいと思います。
JavaがC ++の機能を提供しない場合は、その機能が適切ではないことを意味するため、使用しないようにする必要があります。
これはかなりよく回答されています。JavaはC ++の「良い部分」ではなく、そう考える理由もありません。
特に、個々のC ++機能のメリットは議論の余地がありますが、Javaの設計者が悪い考えだと思ったため、Javaの一部ではないC ++ 11 / C ++ 14の機能の多くは必ずしも除外されません。例として、バージョン8まで、Javaにはラムダはありませんでしたが、C ++ 11標準でC ++に導入されました。Java 8より前は、Javaに欠けているC ++機能が「良くない」ために設計上欠けていたという仮定は、言語機能としてのラムダは「良くない」ことを暗示していました(どこにいるLISPerの恐怖にとってもおそらくあなたが実際に Java が好きだと聞くほど恐ろしいでしょう)。しかし今、JavaデザイナーはラムダにStamp of Approval(TM)を付けているので、今では良いことです。
さらに深く掘り下げると、Java 8でさえ、lambda-as-closureはC ++ 14のラムダほど柔軟ではありませんが、これは、より柔軟なアプローチが悪いという意識的な決定ではなく、JVMアーキテクチャの制限による可能性があります言語設計の観点。
C ++固有の機能(例:フレンド関数、多重継承)を備えたC ++コードは、C ++プログラマーのみが保守またはレビューできますが、JavaのようなC ++(C ++言語固有の機能なし)を記述するだけで、コードは両方によって保守またはレビューできますC ++およびJavaプログラマ。
これが私が対応したかった主なものです。
大まかに言って、使用している言語に精通していないプログラマーからコードレビューを取得することには、いくつかの価値があるかもしれません。関数/メソッドの名前とコメントの明快さに関する貴重なフィードバックを提供できます。また、(質問が正しく示すように)言語が既に知っている1つ以上の言語に類似している場合、基本的なプログラムフローに従うことができます。潜在的に論理エラーをキャッチします。
しかし、それはありませんレビューのこの種は今まで実際に使用している言語を知っている開発者からのレビューや「と同等の」「と同じくらい良い」となることをケース。本質的に、これは、ある言語を別の言語のように見せると通常微妙な違いが隠され、一方、ある言語を別の言語のように振る舞う(特にC ++とJavaの場合)ことは言語にとって非公平であり、かつ/または依然として混乱を招く可能性があるためですレビュアー向け。
まず、C ++をJavaの「見た目」にすることの意味について考えてみましょう。単純なケースとして、new
Javaの場合と同様に、オブジェクトのインスタンス化に使用できます。
Foo foo = new Foo();
しかし、この方法でインスタンス化されたオブジェクト->
は.
、メソッドを呼び出す代わりに使用するため、メソッド呼び出しをJavaのように見せたい場合は、代わりに次のように記述する必要があります。
Foo& foo = *new Foo();
しかし、これは馬鹿げたことではありません。特に、を使用してメモリを後でクリーンアップする必要があります。一部の経験豊富なC ++delete &foo
開発者は、合法的なコードであることに気付かない場合があります。どちらにしても、全体に振りかけ面白い非Javaのような記号があるので、我々はできませんかなりの言語は、Java「のように見える」します。(*new
を使用して削除することもできますが#define New *new
、さらに悪いことに、を使用すると、#define new *new
仲間の開発者があなたを嫌うように懇願します。)そして、上記のようdelete
にJavaには存在しないため、いずれにしても(別の回答)メモリリークなしでJavaのようにオブジェクト使用法を実際に「見える」ようにすることはできません。
しかし、最新のC ++にはスマートな共有ポインタが含まれており、Javaのメモリ管理変数参照によく似ています。だからあなたが書くことができるJavaのどこでも、Foo foo = new Foo();
代わりに書くことができます:
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
今では、実際にJavaの内部によく似た言語機能を使用しています。しかし、突然、C ++以外のレビュー担当者に説明することがたくさんありshared_ptr
ます。これは何ですか?微妙なトリッキーな「落とし穴」はmake_shared
何ですか?(これは、いくつかの失敗例があり、呼び出されている「間違った」コンストラクタにつながることができ、完全な転送を、使用しています。)なぜ方法がで呼び出す必要があります->
が、使用して.
いくつかの方法では、コンパイラによって許可されていますか?(shared_ptr
メソッドが場合。独自のメソッドを持っている)Foo::reset(void)
が存在し、不注意な開発者はでそれを呼び出すようにしてみてくださいfoo.reset()
(一つだけの共有ポインタが存在する場合のそのインスタンスを指している、Foo
基礎となるメモリを削除し、無効になりますコールが発生した場合)foo
、およびJava開発者はこの問題をキャッチする可能性は低いです。
また、C ++が持っているたくさんの落とし穴ある特定の言語を。私の知る限り、ほとんどのC ++開発者は、「安全な」C ++プラクティスの独自のイディオムを徐々に開発することにより、これらの落とし穴に対処することを学びます。 Googleコーディングプラクティスと、「Seasoned C ++のベテランは通常Googleコーディングガイドラインを拒否します」というコメント。言語は複雑すぎるかもしれないとの主張はすべて(少なくとも私の経験では)、「まあ、間違って使うのはやめなさい」というバリエーションに出会うようです。これはC ++コミュニティに対する非常に否定的な見方であり、言語学習者を支援したいと思っている経験豊富な開発者もいますが、 例えば、未定義の振る舞いに対するある種の防御力のようです(たとえば、上記の「落とし穴」リンクの議論の多くを参照してください)。
Java開発者は、コードレビューを介してこれらの落とし穴を見つけて修正するのに役立ちません。
いつかコードをJavaに変換するように求められる場合があります。
設計段階にあるときに将来コードに何が起こるかを考慮しようとすることは、完全に妥当です。
しかし、最初に、この特定の考慮事項は、リモートの可能性のように思われます:コードは通常、そのまま再利用されます(たとえば、JNIインターフェースを使用して、作業C ++コードの一部またはすべてを将来のJavaソフトウェアにプラグインできます)直接手動で「転写」するより。
そして、第二に、あなたは後で言う、
すべてのC ++言語固有の機能(例:多重継承)には、Javaで実装する代替手段が必要です。
これは基本的に、「Javaに変換」ポイントをキャンセルします。ソフトウェアが慣用的なC ++で記述され、その後慣用的なJavaに変換される場合、この変換がC ++機能のJava機能への正確な1対1マッピングを適用することにより行われることを期待する理由はありません。
C ++固有の機能を持たないコードは、通常、メンテナンス性が向上しています。
ここで何を意味するのかは明確ではありませんが、実際にはこれにある程度同意します。細心の注意を払っていない限り、C ++機能は保守性の問題につながる可能性があります。C ++ FQA Liteは(少なくとも実際にはかなりよくそれを理解するように見える誰かから言語とその支持者の重要なウェブサイト)があることを述べて
...開発者の80%が言語の最大20%を理解しています。異なる人々にとって同じ20%ではないので、互いのコードを理解することを期待しないでください。
注意してください:あなたがC ++ファンであり、私の答えでこの点に達し、FQAの作者が実際にC ++を理解していないか、彼の議論のほとんどで不誠実であると主張するコメントに飛び降りたいと思う場合、(1)彼を引用した後の正確に2つの文、FQAは非常に偏りのあるソースであると認めます。(2)FQA作成者がC ++を理解しているかどうかは、私が何を言おうとしても重要ではありません。 、C ++をbashしようとしていないので、FQAを引用したからといって、私が反C ++であると想定せずに、残りの記事を読む必要があります。メモの終わり。
同様に、Linus Torvalds は本質的にこの理由でC ++を嫌っています(警告:リンクは、真の悪名高いLinusスタイルで、多くの宣誓を伴います)。
明らかに、これらは非常に偏った問題ですが、C ++の支持者でさえ、言語機能セットのすべてを使用すべきではないと言うことがよくあります(もう一度、Googleコーディングガイドラインを参照してください;また、C ++の作成者であるBjarne Stroustrup 、「C ++の中には、抜け出すのに苦労しているずっと小さくてきれいな言語があります」と公に述べています。
そのため、特にJavaのバックグラウンドから来ている場合は、C ++の機能は簡単に誤用される可能性があるという考えにはいくつかのメリットがあると思います。さらに、言語の一部に自分自身を制限することにより、これらの問題を軽減するというアイデアにはメリットがあります。
しかし、決定され、別の言語に基づいて使用するサブセットはないではない「異なる言語が」Cでない限り、本当にC ++言語のCのようなサブセットがあるので、正しいアプローチのように見えます。(Linusは上記の彼の暴言でこれを参照し、Scott Meyersはこのサブセットを「サブ言語」と呼ぶこともあります。)Javaのランタイムパラダイム(ガベージコレクション、VM上で実行)は、C ++とは根本的に異なります。 C ++の使用法について学ぶべき有益な教訓があることは明らかではありません。上記のように、Javaから直接C ++についての教訓を引き出しようとすると、非常に非自明なコードにつながる可能性があります。
代わりに、言語の慣用的な使用方法を理解した上で、言語の「受け入れ可能なサブセット」を定義してください。Cが提供する以上のC ++の機能の多くを引き続き活用するかなり制限的なサブセットが必要な場合は、前述のGoogle Codingガイドラインを開始するのに適している場合があります。確かに、いくつかのGoogleの制限には「合理的な議論はない」と言う開発者がいますが、アレクサンドレスクをD言語での仕事(それ自体が何かを伝えるはずです)から雇いたいと思わない限り、それはおそらく大丈夫。C ++をJavaに変換するよりも確かに優れています。
コードガイドラインセットのもう1つの良い出発点は、Bjarne StroustrupとHerb Sutterによる進行中の作業である新しいC ++ Core Guidelinesです。
C ++の欠点に対処する唯一の他の方法は、別の言語を選択することです。あなたはJavaが好きで、このプロジェクトが最終的にJavaに変換される可能性があると思われます。別の答えで述べたように、あなたはただ... Javaから始めることができます。
Java以外の何かを本当に使用する必要がある理由は2つあります。
- 実行時のパフォーマンスが本当に必要です。この場合、C ++をJavaのように扱うことは実際には役に立たないでしょう。共有ポインターなどのJavaのような手法は実行時のパフォーマンスを低下させるからです。
- JVMをまだサポートしていないあいまいなプラットフォームで動作するソフトウェアが必要です。この場合、おそらくGCCまたはClangフロントエンドを備えた言語にこだわっています。CとC ++は明らかな候補ですが、Rustのようなものを調べることもできます。(クイックプラグ:Rustを広範囲に使用したことはありませんが、見た目が素晴らしく、できるだけ早くRustの主要なプロジェクトに取り組むことを切望しており、C ++プロジェクトを開始することを検討しているすべての人がRustを代替として検討する必要があります)
すべてのC ++言語固有の機能(例:多重継承)には、Javaで実装する代替手段が必要です。そうでない場合、設計パターンまたはコードアーキテクチャに問題があることを意味します。
これについてはすでにある程度取り上げましたが、意図的に2番目の文を省略しました。
constexpr
Javaのような部分的にJITの言語では意味をなさないのようなものが、無効なアーキテクチャを示していることを確信していません。テンプレートメタプログラミングの過剰な使用は価値があるよりも多くの問題があるかもしれないという考えをよりオープンにします。特に、constexpr
コンパイル時の関数評価を行うために存在しますconstexpr
が、デザインの欠陥がない場合は明らかです'それを使用しています:コードを実行する前にいくつかの計算が行われるようにするだけです。これは素晴らしいパフォーマンスの向上です(たとえば、別のエントリを除く他のすべてのエントリよりも優れているThe Benchmark Gameのn体問題のこのエントリを参照してください)C ++で書かれた、