関数tryブロック

ロベールのC++入門講座 10-08

コンストラクタの初期化子で発生した例外をキャッチする方法として関数tryブロックというものがあります。

#include <iostream>
#include <string>
using std::cout; using std::endl;

class CSample {
public:
    CSample (std::string str)  try: m_str(str) {
        cout << "コンストラクタ" << endl;
    }
    catch (const std::bad_alloc& e) {
        // std::stringのメモリ確保に失敗した場合にここにくる
    }
private:
    std::string m_str;
};

int main () {
    CSample obj("str");
    return 0;
}

上記のようにm_strの初期化子の前にtry:と書いておくと、コンストラクタのブロックの後にそのままcatchブロックを書くことができます。

見た目の複雑さが玉に傷ですね。こんなことするくらいなら初めから初期化子を使わずに

CSample (std::string str) {
    try {
        m_str = str;
    catch (const std::bad_alloc& e) {
        // std::stringのメモリ確保に失敗した場合にここにくる
    }
}

こうした方が綺麗ですよね。

ちなみにこの関数tryブロックは古いコンパイラではサポートしていないようなので注意が必要です。

DirectXとOpenGL

C++の勉強も順調に進んできたのでそろそろ手を出していこうかなと思います。

これらのライブラリは今までの勉強の仕方のように頭から順に勉強していくスタイルでは無理があります。大量の型やクラスてんこもりなのでいちいち全部覚えてられないです。

なのでまずやりたいことを実現するのにどうやればいいのか?というスタイルで勉強していきたいと思います。

またWebに色々な情報が転がっているのでそれらを参考に試していこうと思います。

DirectXOpenGLか、どちらから手を付けていこうか迷ったのですが、とりあえずDirectXからにします。

DXライブラリというDirectXを用いた素晴らしいライブラリがあるのですが、いきなりそこから入るのもどうかなと思ったのでまずは素のDirectXに触れてみて、機会があればDXライブラリの方も触ってみようかなと思います。

もちろんその間もロベール本でC++の復習もしつつ色々できたらなぁと思います。

DirectXのインストール

まずはインストールしないことには始まらない。

Download DirectX Software Development Kit from Official Microsoft Download Center
http://www.microsoft.com/downloads/details.aspx?FamilyId=4B9B1752-6F6C-440E-816C-35D247570AE4&displaylang=ja


ここでSDKと日本語ドキュメントをダウンロードしてインストール。

日本語ドキュメントは若干古いけど無いよりマシということで。英語ドキュメントとあわせて見るのが良いのかな。

例外の再送出

ロベールのC++入門講座 10-05

例外が発生して関数を抜ける前に何かしらの後処理がしたい場合、以下のように例外の再送出を使います。

#include <iostream>
using std::cout; using std::endl;

void func () {
    int* p = NULL;
    try {
        p = new int[10];
        throw "エラー発生!";
    }
    catch (...) {
        // func関数を抜ける前にpのメモリを解放しないといけない
        delete [] p;
        cout << "pを解放する" << endl;
        // エラー処理は呼び出し側に任せたいので再送出
        throw;
    }
}

int main () {
    try {
        func();
    }
    catch (const char* error) {
        cout << error << endl;
    }
    return 0;
}
$ main
pを解放する
エラー発生!

catchブロック内でthrowを引数無しで呼び出すと、そこでcatchした例外の再送出を行ってくれます。

もしcatchブロックではない場所で引数無しthrowを呼び出すとどうなるのでしょうか?

僕の予想ではコンパイルエラーになるのではと思ったのですが処理が通りました。

ただし、実行時にエラーが発生しました。

#include <iostream>
using std::cout; using std::endl;

int main () {
    try {
        throw;
    }
    catch (...) {
        cout << "error" << endl;
    }
    return 0;
}
$ main
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

どうやらcatchブロック外で引数無しthrowを呼び出すと例外処理ですらキャッチできない例外が発生するようです^^;