【C++】std::exceptionの概要と使い方【標準ライブラリ】

【C++】std::exceptionの概要と使い方【標準ライブラリ】

std::exceptionとは

`std::exception` は C++ の標準ライブラリに含まれる例外の基底クラスです。 すべての標準例外クラスは `std::exception` を継承しており、独自の例外クラスを作成する際にも継承できます。 `std::exception` は以下のような基本的な機能を持っています。


class exception {
public:
    virtual const char* what() const noexcept;
};

`what()` メソッドは、例外の説明をC文字列として返すメソッドです。 標準ライブラリの例外は、このメソッドをオーバーライドしてエラーメッセージを提供します。

基本的な使い方

`std::exception` の基本的な使い方を見てみましょう。


#include <iostream>
#include <exception>

int main() {
    try {
        throw std::exception();
    } catch (const std::exception& e) {
        std::cout << "例外が発生: " << e.what() << std::endl;
    }
    return 0;
}

`std::exception` の `what()` メソッドは `"std::exception"` という文字列を返します。 実際のエラー内容を提供するには、派生クラスを利用するのが一般的です。

派生クラス

C++標準ライブラリには、`std::exception` を継承したいくつかの例外クラスが用意されています。

  • std::logic_error: プログラムのロジックエラー
  • std::runtime_error: 実行時エラー
  • std::bad_alloc: メモリ確保の失敗
  • std::bad_cast: 型キャストの失敗
  • std::out_of_range: 範囲外アクセス

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::runtime_error("実行時エラーが発生しました");
    } catch (const std::exception& e) {
        std::cout << "例外: " << e.what() << std::endl;
    }
    return 0;
}

独自の例外クラスの作成

`std::exception` を継承して独自の例外クラスを作成することも可能です。


#include <iostream>
#include <exception>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "独自の例外が発生しました";
    }
};

int main() {
    try {
        throw MyException();
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }
    return 0;
}

例外安全性

C++では、例外の発生時にリソースリークが起こらないように注意する必要があります。 そのために、RAII(Resource Acquisition Is Initialization)を活用するのが一般的です。


#include <iostream>
#include <memory>
#include <exception>

class Resource {
public:
    Resource() { std::cout << "Resource 確保\n"; }
    ~Resource() { std::cout << "Resource 解放\n"; }
};

int main() {
    try {
        std::unique_ptr res = std::make_unique();
        throw std::runtime_error("エラー発生");
    } catch (const std::exception& e) {
        std::cout << "例外キャッチ: " << e.what() << std::endl;
    }
    return 0;
}

例外の伝播と再送出

例外は関数の外に伝播させることもできます。


void func() {
    throw std::runtime_error("関数内で発生した例外");
}

int main() {
    try {
        func();
    } catch (const std::exception& e) {
        std::cout << "例外をキャッチ: " << e.what() << std::endl;
    }
}

例外処理のベストプラクティス

  • 例外はできるだけ `std::exception` の派生クラスを使う
  • RAIIを活用して、例外発生時のリソース管理を適切に行う
  • 例外はキャッチしたら適切に処理し、むやみに握りつぶさない
  • 例外は「異常な事態」のみに使用し、通常の制御フローには使わない

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です