例外 (C++をもう一度)
[最終更新] (2019/06/03 00:51:40)
最近の投稿
注目の記事

基本的な構文

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

void MyFunc() {
    if(true) {
        throw "MyFunc";
    }
    // 正常時の処理...
}

int main() {

    try {
        if (true) { // エラー判定
            throw "main";
            // throw 1;
        }

        // 関数内からもthrowできます
        MyFunc();

        // 正常時の処理...
    }
    catch (const char* error) { // throwされた値
        // エラー時の処理
        // (↑tryでのみ有効なオブジェクトのデストラクタは、抜ける際に実行済みです)
        cerr << "const char*: " << error << endl;
        return EXIT_FAILURE;
    }
    catch (int error) { // intがthrowされた場合
        try { // 入れ子にできます
            if(true) {
                throw "nested try-catch";
            }
            cerr << "int: " << error << endl;
            return EXIT_FAILURE;
        }
        catch (const char* error) {
            cerr << "const char*: " << error << endl;
            return EXIT_FAILURE;
        }
    }
    catch (...) { // 対応するcatchがないthrowの場合
        return EXIT_FAILURE;
    }

    return 0;
}

例外指定子

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

void MyFunc() throw() { // 例外指定 (← 実用性は低いですが知識として)
    // MyFunc は例外を何も投げない throw() と宣言しているため
    throw 1; // とするとエラーになります
}

int main() {
    try {
        MyFunc();
    }
    catch (...) {
        return EXIT_FAILURE;
    }
    return 0;
}

catch節内でthrowする構文

異なる型の例外をthrowする可能性がある場合

#include <iostream>
using namespace std;

void MyFunc() {
    try {
        throw 1;
    }
    catch (int error) {
        throw "MyFunc";
    }
    catch (const char* error) {
        cerr << "同階層のものは実行されず" << endl;
    }
}

int main() {
    try {
        MyFunc();
    }
    catch (const char* error) {
        cerr << "1つ外のものが実行されます" << endl;
    }
    return 0;
}

同じ型の例外をthrowすることが確定している場合の特別構文

#include <iostream>
using namespace std;

void MyFunc() {
    try {
        throw "MyFunc";
        // throw 1; // int型のthrow
    }
    catch (...) {
        // どのような型のthrowであっても必ず行う必要のある
        // 汎用性の高い処理を記述。メモリ解放など。
        cerr << "caught at MyFunc" << endl;

        throw; // exception rethrow (例外の再送出)
    }
}

int main() {
    try {
        MyFunc();
    }
    catch (const char* error) {
        cerr << "const char*: " << error << endl;
    }
    catch (int error) {
        cerr << "int: " << error << endl;
    }
    return 0;
}

クラス型の例外をthrow

例外は基本型ではなくクラスにするのが通常です。その理解のためにはアップキャストの知識などが必要です。

#include <iostream>
#include <string>
#include <cstdlib>

class MyException {
public:
    MyException(const char* error);
    virtual ~MyException(); // 仮想デストラクタ

public:
    const char* What() const;

protected:
    std::string m_error;
};

class MySubException :
    public MyException
{
public:
    MySubException(const char* str);
};


using namespace std;

MyException::MyException(const char* error) :
    m_error(error)
{
}

MyException::~MyException() {
}

const char* MyException::What() const {
    return m_error.c_str();
}

MySubException::MySubException(const char* str) :
    MyException("MySubException")
{
    m_error += ": ";
    m_error += str;
}

int main() {
    try {
        throw MySubException("main");
    }
    catch (const MyException& e) { // アップキャスト
        cerr << e.What() << endl; //=> MySubException: main
        return EXIT_FAILURE;
    }
    return 0;
}

コンストラクタで例外を投げる

この続きが気になる方は
関連ページ