導入
「ファイルが開けない」「0で割ろうとした」など、正常に処理できない事態が起きたとき、戻り値で毎回エラーを返すのは煩雑です。C++ には「例外」というエラー通知の仕組みがあり、問題の発生箇所と対処箇所を分けて書けます。
この回は読み物です。例外の送出(
throw)はブラウザ内の実行環境では停止してしまうため、手元の環境(g++ / clang など)でコンパイルして動きを確かめてください。前後のモダンC++の回は、そのままブラウザで実行できます。
説明
throw で例外を投げ、try で囲んだ範囲から投げられた例外を catch で受け止めます。throw された時点で処理は中断し、対応する catch まで一気に飛びます。
flowchart LR t["try ブロック"] -->|"throw で例外発生"| c["catch ブロック"] t -->|"正常なら"| n["catch を素通り"]
#include <iostream>
#include <stdexcept> // runtime_error など
using namespace std;
double divide(int a, int b) {
if (b == 0) {
throw runtime_error("0 では割れません"); // 例外を投げる
}
return (double)a / b;
}
int main() {
try {
cout << divide(10, 2) << endl; // 5
cout << divide(10, 0) << endl; // ここで例外 → 下は実行されない
cout << "この行は実行されない" << endl;
} catch (const runtime_error& e) {
cout << "エラー: " << e.what() << endl; // e.what() でメッセージ
}
cout << "続きの処理" << endl; // catch 後、ここから再開
return 0;
}
// 5 / エラー: 0 では割れません / 続きの処理
例外の強みは、深い呼び出しの奥で起きた問題を、途中を飛び越えて一気に上位で処理できることです。前章の RAII と組み合わせると、例外で飛んでもデストラクタが呼ばれ、資源が確実に片付きます。
まとめ
throw で投げ、try/catch で受け止めます。catch (const 例外型& e) で参照で受け、e.what() でメッセージを取ります。例外は「発生」と「対処」を分離でき、RAII と組み合わせて安全なエラー処理を実現します。