C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++とJavaの例外処理を徹底比較!throw・catch・finallyの違いをわかりやすく解説

例外処理は、現代のオブジェクト指向言語のほとんどに備わっている重要な機能です。C++とJavaも例外なくこの機能をサポートしており、両言語ともtry-catchブロックを使って例外を捕捉するという共通点があります。しかし、その仕組みや書き方にはいくつかの重要な違いも存在します。

本記事では、C++とJavaにおける例外処理の類似点と相違点を、具体的なコード例を交えながら詳しく解説していきます。

最大の違い:スローできる例外の型

C++とJavaで最も大きな違いは、「どんなデータを例外として投げられるか」という点にあります。

  • C++の場合: intやcharなどのプリミティブ型はもちろん、ポインタなどあらゆる型のデータを例外として投げることができます。
  • Javaの場合: 投げられるのはThrowableクラス(またはそのサブクラス)のオブジェクトのみです。intなどのプリミティブ型を直接投げることはできません。

C++でint型を投げる例

#include <iostream>
using namespace std;

int main() {
    int x = -5;
    try { // 保護されたコード
        if( x < 0 ) {
            throw x; // int型をそのまま投げられる
        }
    }
    catch (int x) {
        cout << "Exception Caught: thrown value is " << x << endl;
    }
}

実行結果

Exception Caught: thrown value is -5

このようにC++では、数値のような単純な値でも例外として扱えますが、Javaではコンパイルエラーになります。Javaでは必ずExceptionErrorなど、Throwableを継承したクラスのインスタンスを投げる必要があります。

すべての例外をキャッチする方法の違い

C++:catch(...)構文

C++には「catch all」と呼ばれる特殊な構文があり、あらゆる型の例外を一括して捕捉できます。構文は以下の通りです。

try {
    // 保護されたコード
} catch(...) {
    // あらゆる型の例外をキャッチ
}

C++のコード例

#include <iostream>
using namespace std;

int main() {
    int x = -5;
    char y = 'A';
    try { // 保護されたコード
        if( x < 0 ) {
            throw x;
        }
        if(y == 'A') {
            throw y;
        }
    }
    catch (...) {
        cout << "Exception Caught" << endl;
    }
}

実行結果

Exception Caught

Java:Exceptionクラスでキャッチ

一方、Javaですべての例外を捕捉したい場合は、すべての例外クラスの親であるExceptionクラスを指定します。ユーザー定義の例外も含めて捕捉可能です。

try {
    // 保護されたコード
} catch(Exception e) {
    // あらゆる型の例外をキャッチ
}

なお、より広範囲に捕捉したい場合はThrowableを指定することもできますが、通常はExceptionを使用するのが一般的です。

finallyブロックの有無

もう一つの大きな違いが、finallyブロックの存在です。

  • C++: finallyブロックは存在しません。リソースの解放などはRAII(Resource Acquisition Is Initialization)というデストラクタを活用した仕組みで行うのが一般的です。
  • Java: finallyブロックが用意されており、ここに書いたコードは必ず実行されます。tryブロックが正常に完了した場合でも、例外が発生した場合でも、finally内の処理は必ず実行されるため、ファイルのクローズやリソース解放に最適です。

Javaのfinallyブロックの例

public class HelloWorld {
    public static void main(String []args) {
        try {
            int data = 25/5;
            System.out.println(data);
        } catch(NullPointerException e) {
            System.out.println(e);
        } finally {
            System.out.println("finally block is always executed");
        }
        System.out.println("rest of the code...");
    }
}

実行結果

5
finally block is always executed
rest of the code...

この例では、tryブロック内で例外は発生していませんが、finallyブロックのメッセージが出力されていることがわかります。これが「finallyは常に実行される」ことを示しています。

まとめ:C++とJavaの例外処理の比較表

項目C++Java
投げられる例外の型あらゆる型(プリミティブ型・ポインタ含む)Throwableおよびそのサブクラスのみ
全例外のキャッチ方法catch(...)catch(Exception e)
finallyブロックなし(RAIIで代替)あり(常に実行される)
チェック例外なしあり(throws宣言が必要)

両言語ともtry-catchによる基本的な例外処理の流れは似ていますが、C++の柔軟性(何でも投げられる)と、Javaの堅牢性(Throwableに限定され、finallyでリソース管理がしやすい)という、それぞれの言語設計思想の違いがよく表れています。用途に応じて適切な言語の例外処理スタイルを理解しておきましょう。

  1. C++の例外処理入門!try・catch・throwの基本と標準例外クラス一覧

    C++における例外処理(Exception Handling)とは、プログラムの実行時に発生するエラー(ランタイムエラー)を適切に扱うための仕組みです。例外とは、実行時に送出(スロー)されるイベントのことで、C++ではすべての標準例外が std::exception クラスから派生しています。もし例外を捕捉しなかった場合、例外メッセージが出力され、プログラムは強制終了してしまいます。 C++標準では、例外関連のクラスが <exception> ヘッダに定義されており、プログラムの中で自由に利用できます。親子関係によるクラス階層は次のようになっています。 C++の主な標準例外クラス

  2. Javaの例外(Exception)とは?基本概念から例外処理の方法まで徹底解説

    Java開発者にとって、Javaの例外と例外処理に関する知識は必須です。 本チュートリアルでは、Javaプログラミングにおいてすべてのエンジニアが押さえておくべき基礎知識を解説します。まずは「Javaの例外とは何か」というところから始めましょう。 Javaの例外とは Javaプログラムは、実行中に何らかの問題に遭遇し、突如として強制終了することがあります。このような問題を例外(Exception)と呼びます。 優れたプログラマーは、実行時に発生し得るエラーを予測し、例外が起きた場合でもプログラムが別の経路で動作を継続できるように設計します。このような実践が例外処理(Exception Hand