独習C++

C++:12.例外処理: エラーハンドリングの基礎

独習C++

C++プログラムでは、さまざまな種類のエラーが発生する可能性があります。これらのエラーを適切に処理するためには、例外処理の仕組みを理解し、実装することが重要です。例外処理は、プログラムの正常な実行フローを維持し、エラーが発生した場合でも安全に動作を継続するための手段です。この記事では、C++での例外処理の基本的な考え方と具体的な使い方について、サンプルコードと共にわかりやすく解説します。

例外とは何か?

例外とは、プログラムの実行中に予期しない事態が発生し、通常の処理を続行できなくなった際に発生するエラーです。例外処理を行うことで、エラーの原因に応じた適切な対応を行い、プログラムが異常終了しないようにします。C++では、try, catch, throwという3つのキーワードを使用して例外処理を行います。

tryブロック

tryブロックは、エラーが発生する可能性のあるコードを囲むために使用します。もしtryブロック内で例外が発生すると、その後のコードは実行されずに、対応するcatchブロックが呼び出されます。

catchブロック

catchブロックは、tryブロックで発生した例外を受け取り、それに対する処理を行います。catchブロックは、発生した例外の型に基づいて複数定義することが可能です。

throwキーワード

throwキーワードは、例外を発生させるために使用します。throwを使うことで、特定のエラー条件に遭遇したときに例外を投げ、その後の処理をcatchブロックに任せることができます。

C++での基本的な例外処理の例

ここでは、C++での基本的な例外処理の使い方を示します。このサンプルコードでは、整数の割り算を行い、ゼロによる除算が発生した場合に例外を投げて処理します。

#include 

int divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero!");
    }
    return a / b;
}

int main() {
    int x = 10;
    int y = 0;

    try {
        int result = divide(x, y);
        std::cout << "Result: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

このプログラムでは、divide関数内でゼロ除算が発生した場合にthrowキーワードを使って例外を投げています。tryブロック内でdivide関数を呼び出し、例外が発生した場合はcatchブロックでその例外を捕まえてエラーメッセージを出力します。実行結果は以下のようになります。

Error: Division by zero!

複数の例外をキャッチする

C++では、異なる種類の例外を投げることができ、それぞれの例外に対して異なるcatchブロックを用意することが可能です。例えば、整数のゼロ除算に加えて、負数の除算に対しても別の例外を投げるケースを考えてみましょう。

#include 

int divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero!");
    }
    if (b < 0) {
        throw std::invalid_argument("Negative divisor!");
    }
    return a / b;
}

int main() {
    int x = 10;
    int y = -2;

    try {
        int result = divide(x, y);
        std::cout << "Result: " << result << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cerr << "Invalid argument: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

このコードでは、負数の除算が発生した場合にはstd::invalid_argument例外を投げ、それに対応するcatchブロックで処理しています。実行結果は以下の通りです。

Invalid argument: Negative divisor!

例外の再スロー

catchブロックで例外を処理した後、必要に応じて例外を再スローすることができます。これにより、上位の関数で再度例外処理を行うことが可能です。

#include 

int divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero!");
    }
    return a / b;
}

void safeDivide(int a, int b) {
    try {
        std::cout << "Result: " << divide(a, b) << std::endl;
    } catch (...) {
        std::cerr << "An error occurred, rethrowing the exception." << std::endl;
        throw; // 例外を再スロー
    }
}

int main() {
    int x = 10;
    int y = 0;

    try {
        safeDivide(x, y);
    } catch (const std::exception& e) {
        std::cerr << "Caught in main: " << e.what() << std::endl;
    }

    return 0;
}

この例では、safeDivide関数内で例外を捕捉し、再スローしています。main関数内で再度その例外が捕捉され、最終的にエラーメッセージが表示されます。

An error occurred, rethrowing the exception.
Caught in main: Division by zero!

まとめ

C++における例外処理は、プログラムのエラーハンドリングを柔軟に行うための強力なツールです。try, catch, throwの基本的な使い方を理解し、例外を適切にキャッチして処理することで、エラー発生時のプログラムの安定性が向上します。さらに、例外の再スローや複数のcatchブロックを使い分けることで、より洗練されたエラーハンドリングが可能になります。例外処理をうまく活用し、堅牢なC++プログラムを作成しましょう。

購読
通知
0 Comments
Inline Feedbacks
View all comments