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

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

C++における例外処理(Exception Handling)とは、プログラムの実行時に発生するエラー(ランタイムエラー)を適切に扱うための仕組みです。例外とは、実行時に送出(スロー)されるイベントのことで、C++ではすべての標準例外が std::exception クラスから派生しています。もし例外を捕捉しなかった場合、例外メッセージが出力され、プログラムは強制終了してしまいます。

C++標準では、例外関連のクラスが <exception> ヘッダに定義されており、プログラムの中で自由に利用できます。親子関係によるクラス階層は次のようになっています。

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

C++の主な標準例外クラス

例外クラス説明
std::exceptionすべての標準C++例外の親クラスとなる基底クラスです。
std::bad_castdynamic_cast が失敗したときに投げられる例外です。
std::bad_exception予期しない例外を処理するために使用される例外です。
std::bad_allocnew による動的メモリ確保の失敗時に投げられる例外です。
std::logic_errorコードを読めば事前に検出できる論理的なエラーです(※原文の「logic_failure」は誤りで、正しくは logic_error です)。
std::runtime_errorコードを読むだけでは検出できず、実行時に初めて判明するエラーです。
std::bad_typeidtypeid 演算子が失敗したときに投げられる例外です。

例外処理の3つのキーワード

C++の例外処理で使うキーワードは、trycatchthrow の3つです。

  • throw … 例外を発生させ(投げ)、処理の流れを中断します。
  • try … 例外が発生する可能性のあるコードを囲みます。
  • catch … 投げられた例外を受け取り、適切な処理を行います。

try / catch ブロックの基本

C++では、try/catch 文を使って例外処理を行います。例外が発生する可能性のあるコードを try ブロック内に記述し、catch ブロックでその例外を処理します。try ブロック内で例外が投げられると、それ以降の処理はスキップされ、対応する catch ブロックへ制御が移ります。

サンプルコード:オブジェクトの破棄とスタック巻き戻し

#include <iostream>
using namespace std;

class Sample1 {
public:
    Sample1() {
        cout << "Construct an Object of sample1" << endl;
    }
    ~Sample1() {
        cout << "Destruct an Object of sample1" << endl;
    }
};

class Sample2 {
public:
    Sample2() {
        int i = 7;
        cout << "Construct an Object of sample2" << endl;
        throw i;  // コンストラクタ内で例外を投げる
    }
    ~Sample2() {
        cout << "Destruct an Object of sample2" << endl;
    }
};

int main() {
    try {
        Sample1 s1;
        Sample2 s2;
    } catch(int i) {
        cout << "Caught " << i << endl;
    }
}

実行結果

Construct an Object of sample1
Construct an Object of sample2
Destruct an Object of sample1
Caught 7

この出力で注目すべき点は、Sample2 のオブジェクトはコンストラクタ内で例外が投げられたためデストラクタが呼ばれていない一方で、正常に構築済みだった Sample1 のデストラクタは呼び出されていることです。これは「スタック巻き戻し」と呼ばれる仕組みで、例外発生時にすでに構築されたローカルオブジェクトが自動的に破棄されることを示しています。

ユーザー定義例外の作り方

標準の exception クラスを継承し、what() メソッドをオーバーライドすることで、独自の例外クラスを定義できます。

サンプルコード

#include <iostream>
#include <exception>
using namespace std;

struct DivideByZero : public exception {
    const char * what () const throw () {
        return "My Exception";
    }
};

int main() {
    try {
        throw DivideByZero();
    } catch(DivideByZero& e) {
        cout << "Exception caught" << endl;
        cout << e.what() << endl;
    } catch(exception& e) {
    }
}

実行結果

Exception caught
My Exception

what() メソッドについて: what() は exception クラスが提供する public メソッドで、すべての子孫例外クラスによってオーバーライドされています。例外の原因を表す文字列を返します。なお、C++11以降では古い形式の const throw() の代わりに noexcept を指定することが推奨されています。

  1. 【初心者向け】C++の例外処理の仕組みを徹底解説!try・catch・throwの基本から独自例外の作成まで

    C++における例外処理(Exception Handling)とは、プログラムの実行中に発生するエラー(ランタイムエラー)を適切に処理するための仕組みです。例外とは、実行時に送出されるイベントのことを指し、C++ではすべての標準例外が std::exception クラスを基底クラスとして定義されています。 もし例外を捕捉しなければ、プログラムは例外メッセージを出力した後に異常終了してしまいます。例外はハンドリング可能なランタイムエラーであり、適切に処理することでプログラムの堅牢性を大きく向上させることができます。 標準例外クラスの階層構造 C++標準では、例外は <exception&

  2. Pythonの例外処理とは?エラーと例外の違いを初心者向けに解説

    エラーと例外の違いプログラムにおける「エラー」とは、構文エラーのように、コンパイル時(実行前)に発生する問題を指します。たとえば、以下のようなコードは文法的に誤りがあるため、実行する前にエラーとして検出されます。abe = 5実行結果:SyntaxError: cant assign to literalこの例では、文字列リテラルに値を代入しようとしているため、「SyntaxError(構文エラー)」が発生します。このようにコードの書き方自体に問題がある場合は、実行前にPythonインタプリタが検出してくれます。例外(Exception)とは何か一方で、文や式が構文的に正しくても、実際に実行し