JavaとC++の比較
Java文法はシンプルなLALRパーサによって解析できる文脈自由文法である。C++の構文解析は、それよりも複雑である。例えば、Foo<1>(3);は、Fooが変数であれば比較シーケンスであるが、Fooがクラスのテンプレート名であればオブジェクトを生成する。
C++では名前空間レベルの定数、変数、関数が認められている。Javaでは、宣言はクラスやインタフェースの中に書かなければならない。
C++のconstは、「論理的に読み取り専用データである」ことを示す。Javaのfinalは、「変数が再び割り当てられない」ことを示す。const intとfinal intなど、基本型にとってはこれらは概ね等価であるが、C++では変数および定数の宣言時初期化もしくは定義時初期化が必要であるのに対し、Javaでは初期化が一回だけ実行されるという条件が満たされればよい。また、C++のポインタ自身に対するconst修飾は、Javaの参照に対するfinal修飾と同じ意味を持つ。
C++11では、コンパイル時に値が決まる定数式 (constant expression) すなわちリテラルを表すconstexpr修飾子をサポートするようになった。Javaでは通例static finalフィールドで定数を定義する。
C++においてconst修飾されたメンバ関数は、関数内でメンバ変数を変更することができなくなる。Javaには相当機能はない。
Javaにおいてfinal修飾されたメソッドは派生クラスでオーバーライドできなくなる。また、final修飾されたクラスは派生クラスを定義できなくなる。なお、C++11ではJavaのようにメンバ関数のオーバーライドや派生クラスの定義を禁止するfinal修飾子が追加された。
C++はgoto文をサポートする。Javaはサポートしないが、ラベル付break文とラベル付continue文で、構造上ややgotoライクな機能を提供する。実際には、Javaは、コードを読みやすくするため、構造化制御フローを強要する。
C++はJavaが持たないやや低レベルな機能を提供する。C++には、特有のメモリ記憶位置や低レベルオペレーティングシステムコンポーネントを書くために必要なタスクを操るのに役立つポインタがある。同様にして、多くのC++コンパイラはインラインアセンブラをサポートする。Javaでは、そのようなコードは全て外部ライブラリに配置し、Java Native Interfaceを通してアクセスしなければならない。そのため、呼び出しのたびに、大きなオーバーヘッドが発生する。
Javaの配列は第一級オブジェクトであるが、配列の一部分のみを参照するサブ配列は定義できず、インデックス範囲を別途指定する必要がある。また、配列範囲外アクセスのチェックが強制される。
C++では関数へのポインタ(あるいは関数への参照)によって、関数あるいはメンバ関数を間接参照することができる。また、ポインタによって関数オブジェクトを指す方法もある。Java 7以前では代替方法としてインタフェースを利用するしかなかったが、Java 8ではメソッド参照の機能が追加された。
C++ではプログラマが演算子を多重定義できる(利用者定義演算子)。Javaは演算子多重定義をサポートしない。文字列型java.lang.Stringに対してのみ、文字列連結が可能な演算子+と+=が予め用意されているだけである。
Javaはリフレクションや任意に新しいコードを動的ロードする機能をサポートする標準APIを持つ。
Javaは1.5以降でジェネリクスをサポートする。C++はテンプレートによりジェネリックプログラミングをサポートする。
JavaとC++はいずれも、ネイティブ型(これらも"基本型"または"組込型"として知られる)とユーザー定義型(これも"複合型"として知られる)を区別する。Javaでは、ネイティブ型は値としての意味しかなく、複合型は参照としての意味だけを持つ。C++では、すべての型が値としての意味を持つが、任意の型の参照を作ることが可能である。
C++は任意のクラスの多重継承をサポートする。また、状態の多重継承にまつわる問題を回避するための機構として、仮想継承をサポートする。