Index

HOME > プログラムTOP > C++



C++の壺・例外処理篇

 C++の基本テクニックのTipsです。例外または例外エラーとは、実行時エラーのことです。これは、コンパイル・エラーと区別され、プログラマ自身が対処すべきエラーです。例外処理篇では、C++に用意されている例外処理構文を使って、簡単なエラー処理の方法を紹介します。
[index] try...catch...構文 ... 例外処理の構文とthrow文
例外情報の管理 ... 例外の型設定と引数、及び処理されない例外
複数のcatchブロック ... catchブロックが複数ある構文、及び特殊なthrow文

sasaraan programming

Exposition

●try...catch...構文

 C++ では、例外処理をするための try...catch... 構文が用意されています。下記のように、tryブロックで例外エラーを捕捉し、catchブロックでエラー処理を行います。例外エラーを発生させたい時は、try文の中で、throw文を使って行います。tryブロック以外で throw を使用すると通常は強制終了となります。
try {
  ... ... ...   // 例外の発生が予想されるプログラム
  throw ...  // 例外発生→catchブロックへ
} catch(型 仮引数) {
  ... ... ...   // エラー処理のプログラム
}
 throw文は、tryブロックで発生するのであれば、外部の関数に委託することも可能です(下記サンプルの右側)。また、throw文からは、エラー情報を渡すことができます。 "throw ..." の "..." の部分がそれに当たります。これは、catchブロックの仮引数 に渡されることになります。これを利用して、様々なエラーをひとつの catchブロックで受け取り、その種類によって、処理を分岐させることができます。
 なお、例外発生後のtryブロック内のコードは実行されないので注意が必要です。
// try...catch... 構文の基本
#include <stdio.h>    // printf
#include <conio.h>    // getch

// main 関数
void main() 
{
    // try...catch...構文
    try {
        throw 1;
        printf("正常処理\n");  // 実行されない
    } catch(int ex) {
        printf("エラー : No.%d\n", ex);
    }

    if (getch()) return;
}    
// throw文を他の関数に委託
#include <stdio.h>    // printf
#include <conio.h>    // getch

void func() {
    throw 1;
}

// main 関数
void main() {
    try {
        func();
    } catch(int ex) {
        printf("エラー : No.%d\n", ex);
    }
    if (getch()) return;
}    
 上記プログラムは、いずれも、「エラー:No.1」と、出力されます。この時、No.1 の最後の「1」は、throw文で渡された値です。

●例外情報の管理

 catch文には様々な型の引数を渡すことができます。前節のサンプルでは int型を用いています(int ex の部分)が、文字列や構造体、クラスを渡すことも可能です。以下左側はクラスのオブジェクト(インスタンス)を渡す例です。この時、try ブロックで宣言したオブジェクトは、tryブロック内を抜ける時に破棄されます。
// クラスを利用する例
#include <stdio.h>    // printf
#include <conio.h>    // getch

class CDemo
{
public:
    CDemo() { printf("コンストラクション\n"); }
    ~CDemo() { printf("デストラクション\n"); }
    void Show() { printf("例外エラー\n"); }
};

// main 関数
void main() {
    try {
        CDemo D;
        throw D;
    } catch(CDemo ex)  {
        ex.Show();
    } 
    if (getch()) return;
}    
// 処理されない例外
void main() 
{
    try {
        throw "エラー";
    } catch(int ex)  {
        printf("例外処理\n");
    } 
    if (getch()) return;
}
// すべての例外を捕捉
void main() 
{
    try {
        throw "エラー";
    } catch(...)  {
        printf("例外処理\n");
    } 
    if (getch()) return;
}    
 一方、例外を throw したにもかかわらず、処理すべき catch ブロックが見つからない時、プログラムは強制終了となります。上記右上の例では、文字列型を処理する catch ブロックがないため異常終了となります。逆に、"catch ( ... )" と記述すると、すべての例外を捕捉することができます。

●複数のcatchブロック

 catch文は複数設置することが可能です。下記左側の例では、int 型、文字列型、その他のすべての型、の順番で例外を捕捉するようにしています。
 このように、例外の捕捉は上から順番に行われます。特に、派生元クラスと派生先クラスを同時に使うような時には、派生元クラスを先に記述してしまうと、派生先クラスの例外処理ができなくなってしまう可能性がありますので、注意が必要です。
// 複数のcatchブロック
#include <stdio.h>    // printf
#include <conio.h>    // getch

// main 関数
void main() 
{
    try {
        throw "エラーです!";
    } catch(int ex)  {
        printf("ErrorNo.%d\n", ex);
    } catch(char* ex) {
        printf("%s\n", ex);
    } catch(...) {
        printf("例外エラー\n");
    }

    if (getch()) return;
}    
// オペランドなしthrow文

void func() {
    try {
        throw "エラー発生!";
    } catch(char* ex) {
        throw;
    }
}

// main 関数
void main() {
    try {
        func();
    } catch(char* ex) {
        printf("%s\n", ex);
    }
    if (getch()) return;
} 
 また、catch ブロックからも例外を投げることが可能です。この時、単に "throw;" と記述すると、今受け取っている例外をそのまま投げることになります。上記右側の例では、func 関数内で発生した例外を メイン関数でそのまま受け取っています。

www.sasaraan.net

(c) morijoh