12項 例外の発生のさせ方と引数引き渡し・仮想関数呼び出しとの違いを理解する

例外の発生のさせ方と引数引き渡し・仮想関数呼び出しとの違いを理解する



throwでオブジェクトを投げる時は、受け取り型が実態であれ参照であれ、そのオブジェクトのコピーが作られます。その時、コピーコンストラクタが呼び出されます。

void throwWidget()
{
    Widget w;
    throw w; //wのコピーを投げる。
}

throwされるオブジェクトがstaticであっても、コピーが作られます。



次の2つのcatchブロックには、大きな違いがあります。

catch (Widget &w)
{
    ...
    throw ;
}

catch (Widget &w)
{
    ...
    throw w;
}

1つ目は受け取ったオブジェクトをそのまま投げているのに対し、2つめは受け取ったオブジェクトのコピーを作成してから投げています。



例外をcatchする時、数値型の暗黙の型変換は行われません。catchしたい数値型は、throwされた型と一致してなくてはいけません。

try
{
    throw 1;
}
catch (double d) //catchできない
{
    ...
}

catch節には、2種類の変換が適用されます。
1つ目は、継承された時の変換です。基底クラスのオブジェクトに対するcatch節は、派生クラスのオブジェクトも補足します。

class runtime_error : public exception{...};
class range_error : public runtime_error {...};
class overflow_error : public runtime_error {...};

catch (runtime_error &r){...} //runtime_error, range_error, overflow_errorを補足する。

2つ目は、void*を受け取るcatch節に対する変換です。void*を受け取るcatch節は、すべてのポインタを補足します。

catch (void *p){..} //すべてのポインタを補足する。