web-dev-qa-db-ja.com

C ++にはあるがJavaにはない)言語機能は避けるべきですか?

プロジェクトの環境により、C++の使用に制限されているとします。 C++にはあるがJavaにはない(たとえば、多重継承、演算子のオーバーロード)など)の一部の言語機能の使用を禁止するのは良いことですか?

その理由は次のとおりです。

  1. JavaはC++より新しいので、JavaがC++の機能を提供しない場合、それは機能が良くないことを意味するので、避けるべきです。それを使用します。
  2. C++固有の機能(例:フレンド関数、多重継承)を備えたC++コードは、C++プログラマーのみが保守またはレビューできますが、Java(C++言語固有の機能なし))のようにC++を記述するだけの場合、コードはC++とJavaプログラマーの両方が保守またはレビューできます。
  3. コードをJavaいつかに変換するように求められる場合があります
  4. C++固有の機能を持たないコードは通常、より保守しやすい
  5. すべてのC++言語固有の機能(例:多重継承)には、Javaで実装する代替手段が必要です。そうでない場合は、デザインパターンまたはコードアーキテクチャに問題があることを意味します。

本当?

112
ggrr

いいえ、これは悲惨でひどく見当違いです。

  • Java機能はC++機能よりも優れているわけではありません。
  • プログラマーが機能の使用方法を知らない場合は、より優れた開発者を訓練または採用してください。開発者をチームの最悪のものに制限することは、優れた開発者を失う迅速かつ簡単な方法です。
  • [〜#〜] yagni [〜#〜] 。将来の問題のゴーストではなく、実際の問題を今日解決してください。
306
Telastyn

順番にご質問にお答えします。

  1. JavaがC++が備えている機能を提供していない場合、それはその機能が適切ではないことを意味するので、使用しないようにする必要があります。

はい、Javaにない機能はすべてハードドライブ上のアナテマです。コードベースから焼き付ける必要があります。従わなかった人々は、彼らの魂がRAIDの神々をなだめるために使用されたので、だまされます。

  1. C++固有の機能(例:フレンド関数、多重継承)を備えたC++コードは、C++プログラマーのみが保守またはレビューできますが、Java(C++言語固有の機能なし)のようにC++を記述するだけの場合、コードはC++とJavaの両方のプログラマーが保守またはレビューする。

疑問がある場合は、チームの最も能力のないメンバーのコードを記述してください。コードは書かれたよりもはるかに頻繁に読み取られます。そして、あなたが書くことができるほど賢いコードは、読むにはあまりにも賢いです。フロントデスクのスタッフが理解できないコードレビューは拒否する必要があります。支援するために、週末にVisual Basic 2.0でプログラミングする方法を彼らに教えてから、使用している言語でコーディングスタイルをエミュレートします。

  1. いつかコードをJavaに変換するように求められる場合があります

ほんとだ!しかし、なぜJavaに立ち寄るのでしょうか。ある日、コードを基本的なアセンブラーやPerlに変換するように求められる場合があります。あらゆる言語のPerlインタープリターが存在するため、プログラムを長いPerl文字列として記述し、選択した言語で引数をマーシャリングします。

言語を変更する必要がある場合は、Perl文字列をラップするコードを書き直してください。

  1. C++固有の機能を持たないコードは通常、より保守しやすい

使用する機能が少ないコードの方が保守しやすいのは事実です。すべての言語はチューリングマシンと同等であり、チューリングマシンはプログラミング言語の機能が最も少ないため、上記のPerlインタープリターで実際にチューリングマシン(テープなど)を実行して問題を解決します。

  1. すべてのC++言語固有の機能(例:多重継承)には、Javaで実装する代替手段が必要です。そうでない場合は、デザインパターンまたはコードアーキテクチャに問題があることを意味します。

C++言語固有の機能には、実際に価値のある用途があります。彼らはJavaではないので、彼らは嫌悪感であり、それを使用する人は異端者と名乗ることができます。 C++にこれらの言語機能がなかった場合、犠牲にする必要のある言語機能を見つけることができません。 C++言語機能は問題を解決します!


見て、C++とJavaには異なる機能セットがあります。 C++とJavaの共通部分でプログラミングすると、両方の言語の利点のほとんどが失われたコードになります。

Javaは、一部のC++機能の乱用に対する反応として部分的に開発されました。これは、特に機能が成熟した数年後、反応が正当化されたことを意味するものではありません。

演算子のオーバーロードで恐ろしいことをすることができます。しかし、すべてのコードがその言語で書かれるのを止めない限り、言語は恐ろしいコードがその言語で書かれるのを防ぐことができません。

また、演算子のオーバーロードを使用して非常にエレガントなことを行うこともできます。複素数または行列のように機能する複素数または行列クラスのような単純なもの。

Javaで使用できないC++機能の使用に関する注意は、注意して表示する必要があります。現在のスキルレベルの現在の一連の開発者が機能を理解していないからといって、その機能を使用してはならないという意味ではありません。同時に、機能を使用できるからといって、そうする必要があるわけではありません。ただし、Javaを多用するショップでは、Java以外の機能以外の機能に対する抵抗よりも抵抗が強くなる可能性があります。

言語間でのコードの変換は、構造的にどのように類似していても、書き換えで行うのが最善です。そのような書き直しなしでそうしようとすると、惨めに失敗するでしょう。

多くのC++固有の機能は、メンテナンスには不思議です。型消去(std::functionなど)を使用すると、階層を分離して、依存関係を減らすことができます。スマートポインターと確定的ライフタイム、およびRAIIにより、実行時の驚きが減り、リソースのボイラープレートが邪魔になりません。重い静的型チェックは、コードが機能せず、コンパイルに失敗することを意味します。ミックスインはコードの重複を減らします。 ADLを使用すると、型階層間のインターフェイスをアドホックに独立して拡張できます。 Lambdaを使用すると、コードを使用する場所の横にコードを記述できます。転送と移動によりコピーが削減され、機能的なスタイル(副作用のない)プログラミングが効率的になります。演算子のオーバーロードにより、ラインノイズが減少し、コードがモデリングしている数学のように見えます。

チューリングタールピットに注意してください。すべてを任意の言語で実装できます(テープ付きの未加工のチューリングマシンを含む)。ただし、これはすべきであることを意味するわけではありません。 C++でJava風の構造を使用してC++機能をエミュレートすることは恐ろしい考えです。その結果、誰も読むことも理解することもできない、保守不可能なコードになります。

Javaデザインからinspirationを取得して、C++に移植できます。構文が好きなので、Python言語機能をC++で実装するのが大好きです。しかし、それは、クラスメソッドを明示的なselfを取る静的メソッドとして記述してから、非静的メソッド呼び出しをそれに転送するラッパーを記述することを意味するのではありません。

最近のC++は、Javaがエミュレートされて拒否されている言語とそれほど似ていません。 1つの言語の機能に縛られないでください。 「本当の言葉」はありません。新しい言語とその機能について学び、その特徴を吸収します。

94
Yakk

私はあなたの理由に答えるつもりです:

  1. どのようにしてその結論に至ったのか理解できません。言語によって機能が異なります。スコープ、言語のアーキテクチャー、時にはクリエーターの好みなど、さまざまな理由によります。言語の一部の機能は悪いかもしれませんが、あなたの一般化は明らかに間違った私見です。
  2. Java=のようにC++を記述すると、コードの質が低下する可能性があります。たとえば、C++ 11の最近では、new/deleteの使用は避けますが、共有ポインタを使用します。シナリオでは、new/deleteのみに依存します。プログラマがJavaしか理解していない場合は、Javaをトレーニングするか、より優れたJavaを採用してください。
  3. それは起こりそうですか? Javaで書いてみませんか?新しい言語でプログラムをゼロから書き直すのは 一般的には悪い考えです と思います。そのようなリスクの正当化。
  4. これは単なる仮定です。
  5. IMHOは、シナリオやユースケースに大きく依存します。
56
Simon

Javaには、組み込みの高速で信頼性の高いガベージコレクター、単一ルートのオブジェクト階層、強力なイントロスペクションなど、C++にはない機能があります。

Javaの他の機能は、Java専用の機能と連動するように設計されており、新しい機能が不足を補うため、JavaのC++機能の省略の多くが可能です。たとえば、Javaには、確定的なデストラクタを持つスタック割り当てオブジェクトはありませんが、最終的にブロックがあります(Java 7以降のtry-with-resources))。この不足を埋め合わせるガベージコレクター。

C++には、finallyブロックやガベージコレクションはありません。 Java(ファイナライザは数えません))に存在しないためにデストラクタを使用しない場合、リソース管理のCレベル(つまり、すべてのマニュアル)を使用しますが、 Javaもgotoを持たないため、クリーンアップを移動先のクリーンアップブロックにグループ化することさえできません。保守性が向上すると本当に思いますか?

Javaには、すべてのクラスが最終的にObjectから派生する包括的なオブジェクト階層があり、いくつかのプリミティブ型をそのようなクラスに自動ボックス化することもできます。これにより、オブジェクトへのポインタを保持するために、オブジェクトのコンテナを1回書き込むことができます。 Java 5はジェネリックを導入しました。これにより、このようなコンテナーが必要とするキャストを取り除くことができますが、それでもほとんど同じコードにコンパイルされます。

C++にはそのような階層はありません。複数のタイプで機能するコンテナーの作成を容易にするために、さまざまなタイプに対して必要に応じてコンパイラーによってインスタンス化されるブループリントであるテンプレートを使用します。テンプレート(およびマクロ)の使用を禁止し、異なるコンテナータイプに対して同じコンテナーコードを繰り返し作成するか、またはvoidポインターを使用するというCルートを使用しますか? (ちょっと待って、Javaにはvoidポインタがありません!)これにより、保守性が向上しますか?

まともな言語には、連携して動作するように設計された多数の機能があります。言語Bには機能がないため、言語Aの機能を禁止することで、Bの機能を一貫したものにするBの機能を同時に追加しないため、言語Aに障害が発生します。

C++の許可された機能を制限してはならないということではありません。 C++は、歴史的に成長した大きな言語であり、プログラマーが安全性と使いやすさを超えてやりたいことを実行できるようにすることを強調しており、優れたプログラムを作成するために、柔軟性のすべての機能が必要なわけではありません。一部の機能の使用を制限する多くのコーディング標準があります。たとえば、Googleのガイドラインでは、主に多重継承、複雑なテンプレート、および例外が禁止されています(ただし、最後のものは歴史的な理由によるものです)。ただし、「Javaにないため)」機能は禁止されていません。これらの機能はC++のフレームワーク内でのみ考慮されます。

26
Sebastian Redl

完全に合理的な結論と思われる数値にすでに到達している場合に、別の回答を投稿するかどうかについて、私は議論しました。つまり、あなたのアイデアは、基本的に災害の発生を待っているということです。しかし、彼らはその結論の背後にあるいくつかの関連性の高い理由を指摘することに失敗したと思います。

JavaとC++の違いmuchは、焦点を当てているように見える詳細よりも深く実行されます。

たとえば、C++での多重継承の禁止について話します。まず、これが単にポイントを欠いていることを指摘しておきます。 Javaは、「インターフェース」を「クラス」とは別のものとして定義します。1つのクラスは他の1つのクラスからのみ継承しますが、任意の数のインターフェースを実装できます。

C++は、この2つの概念を分離していません。最も近いアナログC++は、別のクラスから継承するJava isでインターフェイスを実装するために提供しています。そのため、2つを適切に整列させるには、おそらく- 必要 C++で多重継承を使用するが、基本クラスの一部をほぼ同じ方法で制限したいJavaクラスと比較してインターフェースを制限する(つまり、基本的には関数のシグネチャを指定しますが、少なくともほとんどは実装ではありません)。

しかし、それは2つの実際の違いの表面をかすかに引っ掻いているだけです。実際には、Javaコードはインターフェースを定義する可能性が高く、それらのインターフェースを実装するクラスは、C++コードがanyで動作するいくつかのテンプレートを定義する可能性がはるかに高いです。 =その要件を満たすクラス(指定するインターフェースを実装するために明確に定義されたものだけではありません)。

基本的に「C++構文を使用したJava」であるコードが正直に必要な場合は、後者に類似したものをすべて禁止する必要があります。 Javaジェネリックサポート)である「Tのコンテナ」のレベルにテンプレートの使用を制限する必要があります。残念ながら、これを行うと、誰もできないような混乱したC++コードになります。他のプログラミング言語に翻訳する長期的な可能性は言うまでもなく、現在の状態を維持してください。

将来、他の言語に変換できるコードが本当に必要な場合は、できるだけクリーンで読みやすいコードにするようにしてください。理想は、疑似コードを記述し、それを実行させることです。よく書かれた最新のC++アプローチは、あなたが提案したサブセットよりもずっと理想的なアプローチです。どのように記述しても、Javaに変換する場合は、個々のステートメントの構文だけでなく、実際にコードを変換する必要があります。

25
Jerry Coffin

言語Xでコードを記述する場合は、時間をかけて適切に言語を学習し、問題を解決するために提供されるすべての機能を使用してください。日本語から英語、またはJavaからC++へ)を問わず、ある言語から別の言語への「Word for Word」翻訳を行おうとすると、悪いことが起こります。問題を使用して、使用されている言語に最も自然な方法で解決策を表現します。

何年も前に、インデントのないCプログラムを見て、すべてのステートメントが列7で始まったのは、コードの作成者がたまたまCを使用していたFortranプログラマだったからです。私はポインターへのポインターに言及する心を持っていなかった、私は彼らがその場で気絶していたと思います。

このコードを将来維持するために誰かを雇うことを想像してみてください。それが優れたC++コードであれば、有能なC++開発者を雇うことができ、彼らは自分の道を見つけることができるはずです。 「Java in C++」の場合、C++もJava開発者もコードを理解するのは簡単ではありません。

11
Tom Penny

あなたのすべての理由が反証される可能性があります:

JavaがC++が備えている機能を提供していない場合、それはその機能が適切でないことを意味するので、使用しないようにする必要があります。

機能が良くないという意味ではありません(機能が本質的に悪いわけではありません)。これは、機能が頻繁に誤用された(または、ダイレクトポインターとガベージコレクションのような基本的な概念のために実装できない)ことを意味します。 Javaの定義は、より簡単でよりプログラマーに優しいことを目的としているため、簡単に悪用される可能性があることが判明した機能は削除されます。

C++固有の機能(例:フレンド関数、多重継承)を備えたC++コードは、C++プログラマーのみが保守または確認できますが、JavaのようにC++を記述するだけで(C++言語固有の機能なし)、コードを保守できます。または、C++とJavaプログラマーの両方がレビューします。

ああ?最も単純なC++コードを見てみましょう。

int len = mystring->size();

おっと、「言語固有の」機能は使用されていませんが、Java開発者はすでにメンテナンスできません! Javaでは "。"で逆参照するからです。ここでは「->」です。

いつかコードをJavaに変換するように求められる場合があります

またはC#。またはHaskell。またはPython。またはルビー。またはCOBOL(はい、できます!)どうすれば未来を伝えることができますか?

C++固有の機能を持たないコードは、通常、より保守しやすくなります。

正反対。すべての機能は、プログラミングをより簡単にするために導入され、より保守しやすくなっています。例:フロートで動作するプログラムを取ります。次に、複素数を処理するようにアップグレードします。オペレーターが救助のために過負荷になっています!

すべてのC++言語固有の機能(例:多重継承)には、Javaで実装する代替手段が必要です。そうでない場合は、デザインパターンまたはコードアーキテクチャに問題があることを意味します。

しかし、Javaには多重継承があります!それは「インターフェース」と呼ばれます。 Java実装は、すべてがObjectから派生することによって引き起こされる恐ろしいひし形を回避するための問題のある回避策です。これは、interfaceから派生しないものにすることを唯一の目的とするObjectを導入することによって行われます。 C++にはこの問題はありませんでした。必須の共通ベースがないため、すべてのクラスが恐ろしいひし形なしでインターフェースとして機能できます。

補足:Java最近導入された...インターフェースの具体的なメソッド。 C++が常に存在しない問題を解決しなければならない機能を追加しました。

また、「C++にはあるがJavaにはないもの」についてはほとんど言及していません。 C++とJavaの最大の違いの1つは、メモリレイアウトの制御です。オブジェクトへのポインタの配列を作成できます(Javaの場合と同様)OR連続したメモリブロックを作成できます。ここで、Java開発者を誤解させる可能性のあるC++機能について心配した場合、これは、多重継承やオーバーロードされた演算子など、一目でわかるよりもはるかに上位にランクされ、私のリストにランク付けされるような隠された微妙なものです。 。

結論:クリーンなコードはクリーンなコードです。 JavaまたはC++-同じ違い。単純にしてください。不要な複雑化は、不良コードの主な原因です。

7
Agent_L

いいえ、通常、JavaのようにC++を記述しないでください。また、JavaにはないC++言語機能を絶対に省略しないでください。

1つは、Javaはガベージコレクションされているため、C++の "delete"キーワードに相当するものがないためです。そうすると、削除せずにプログラムを実装することになります。これは、規則により許可されていないためです。

おめでとうございます。メモリリークが発生しました;)。これも理論的ではありません。私は、この正確な状況がオープンソースゲームで発生するのを見てきました。

同様に、Javaには、一般的な関数呼び出し規則のlotを除外するC++ポインターのようなものはありません。 。

避けるべきC++の機能がありますが(以下を参照)、「Javaに含まれていない」ことはリトマステストとしては適切ではありません。


より適切なガイドラインは次のとおりです。

  1. 言語、環境、およびツールに適したコードを記述します。
  2. あなたのチームが理解できるコードを書いてください。
  3. チームが所定のドメインで有能であることを確認してください。

項目(3)は、JavaプログラマーのコードをC++でトレーニングせずにC++でコーディングしてはならないことを意味します。微妙だが非常に重要な違いがあり、扱いようとすると学習できない場合があります。それはJavaの奇妙な方言のようです。

項目(2)は、あなたのチームが多重継承(例えば)で特に不快であり、使用しない適切な解決策がある場合その場合、その代替ソリューションを使用するのが最善です。ただし、これはチームによって異なります。一方、チームがその代替ソリューションの方が多重継承よりも不快な場合は、多重継承を使用してください!


最後に、C++の言語機能には、間違いなく避けるべきものがあります。これらが何かを知りたい場合は、異なる言語のプログラマーではなく、C++プログラマーに尋ねてください。開始するいくつかの例は ポインタ演算 (普遍的なコンセンサスなし)とgotoです。

6
Ethan Kaminski

プロジェクトの環境により、C++の使用に制限されているとします。 C++にはあるがJavaにはない(たとえば、多重継承、演算子のオーバーライド)など)の一部の言語機能の使用を禁止するのは良いことですか?

番号。

「プロジェクトの環境によって」C++の使用に制限されている場合、個人的にどの程度好む/希望するかに関係なく、他のテクノロジーについてthinkingを指摘することはほとんどありません。それを使用/伝道する。
「テクノロジーX」または「Y」が特定の機能をサポートするかどうかは、C++アプリケーションのビルド方法に何も関係ないが必要です。
これはおそらくC++アプリケーションであり、おそらく(現在または過去に)いくつかの「良い理由」のために記述しますas C++アプリケーションで、特定の「ツールボックス」が提供するものをすべて使用します。

If and whenアプリケーションを他のテクノロジーに移植する必要があります(そしてonly then)他のプラットフォームの機能を検討するかもしれません。 可能性がありますが発生することはありません。ただし、大規模な書き換えは高価でリスクの高い操作であることを覚えておいてください。そうする理由が非常になければ、経営陣が引き継ぐことはまずありません。

Visual Basic [.Net]の世界でも同様の(「使用するかしないか」)の議論が数年ありましたが、誰かが[コア言語]を使用せずにVisual Basicアプリケーションを作成するべきだという明るい考えを持っていましたMicrosoft.VisualBasic名前空間によって提供される機能。これは、std ::名前空間なしでC++アプリケーションを作成しようとするようなものです。はい、それは可能ですが、なぜ地球上で正しい考えを持つ人がそうするのを邪魔するのでしょうか?

5
Phill W.

現在の答えはすべて、これは悪いことだと言っています。使用している言語を利用し、C++機能がJAVEにないという理由だけで「悪い」わけではない理由を説明する必要があるためです。 別の角度からお答えします。

多重継承、演算子のオーバーロード、独自のテンプレートの定義などの複雑なC++機能を回避することは1つのことです。

しかし、最も単純なタスク以上のことを行う問題:

  • メモリを割り当て、
  • そのお金をポイントで結びます
  • データ構造を構築する
  • 安全なときにメモリを再利用できます

上記を可能にするJavaおよびC++の共通のサブセットはありません。したがって、あなたが求めていることを行うことは不可能です。(Java C#の場合、どちらもガベージコレクターを使用するので、可能性ははるかに高くなります。)

ただし、Java開発者が何をするか(しかし詳細な「方法」ではない)を理解できるようにコードを書くことを要求でき、これは賢明です。

C++とJavaの両方で実装した独自の言語を設計することもできます。

2
Ian

他のコーダーが理解できないコードを誰も書くべきではありません。言語ロックが問題であると思われる場合は、開発者ロックを取得するまでお待ちください。 1つは他より人質を保持する可能性が高いです。

技術的な理由はまったくありません。あなたが作成したのは、なんらかの理由で言語が使用されたシナリオですが、現在および将来の開発者の多くはそれを実際に理解していません。

私の推測では、Java開発者はJavaで書く方法でC++を書く可能性が高いので、なぜそれをルールにするのでしょう。実装と保守が簡単なC++固有の機能をいくつか発見するかもしれません。 Java開発者のための小さなC++命令/ドキュメント=Javaの大きなボールよりも、開発者が困っていると混乱します。

これは、BASICプログラマーがオブジェクト指向言語に移行する際の問題についての議論です。彼らがOOPプラクティスを理解していない新しい開発者を犠牲にして実践しているのではなく、まったく実装していないのです。そうした場合、彼らは通常それを誤解します。何かがうまくいかない場合は、理由に関係なく削除する必要があります。

誰かが盲目的にコードをコピーして貼り付けるだけでなく、とにかく理解していない多くの領域でそれを行うでしょう。

0
JeffO