ショートカット
ファシリテーター × あり方
コーディングの向こう側
Hello, ANOTHER world!
オブジェクト指向のはなし
プログラミングのはなし
C言語実力診断クイズ
eSkillBooks
プログラミングのはなし

throw する

try-catch や throw というのがあるのは知っているけれど、使い方が良くわからないということはありませんか?それはおそらく、C++ の解説書によく載っている次のような例題が原因でなのではないでしょうか?

SAMPLE
CODE
try {
    int *pi = (int *)malloc( sizeof(int) );
    if ( pi != 0 ) {
        *pi = 100;
    }
    else {
        throw "NO MEMORY!";
    }
}
catch ( const char *pcMsg ) {
    puts( pcMsg );
}

これでは if や while のような制御構文とたいして変わらないように見えます。しかし、try-catch と throw は単なる制御構文ではありません。もっとダイナミックな仕組みなのです。

前のトピックで、次のような「失敗しない関数」について説明しました。

SAMPLE
CODE
void *Storage( size_t sz )
{
    void *pv = malloc( sz );
    if ( pv == 0 ) {
       // エラー処理
        puts( "NO MEMORY!" );
        ABORT();
    }
    
    return pv;
}

void main()
{
    int *pi = (int *)Storage( sizeof(int) );
    *pi = 100;
}

この方法の弱点は、実行時エラーが発生した場合に、そのときの状況によって適切なきめ細かい対処ができないという点です。普通は、いつでも ABORT すれば良いというわけにはいかないでしょう。リカバリーをを試みたり、データを保存してから終了したりする必要があるかも知れません。

C++ では、このようなきめ細かいエラー処理が可能です。それには throw を使います。例えば次のようにします。

SAMPLE
CODE
void *Storage( size_t sz )
{
    void *pv = malloc( sz );
    if ( pv == 0 ) {
       // エラー処理
        throw "NO MEMORY!";
    }
    
    return pv;
}

void Sub()
{
    int *pi = (int *)Storage( sizeof(int) );
    *pi = 100;
}

void main()
{
    try {
        Sub();
    }
    catch ( ... ) {
        ABORT();
    }
}

main 関数の先頭に try-catch を記述して、throw に対するデフォルトの処理を定義しています。この例は、基本的にはその前の例と同様の動きをします(メモリ不足の時には異常終了します)。実行時エラー処理のロジックを毎回書く必要もありません。しかし、ローカルの try-catch を記述すれば一時的にエラー処理の内容を変更できます。エラーに強くて、楽で、柔軟です。

このような try-catch と throw による例外処理機構は C 言語では実現できません。C++(または Java)が必要です。

(「プログラミングのはなし」は1998年1月から1999年1月にかけて作成されたコンテンツです。)