C++異常タイプおよびマルチレベルcatch
ソース:https://www.jianshu.com/p/3858e8c3c822まず、前節で述べたtry-catchの使い方を振り返ってみましょう.
次の質問はcatchキーワードの後ろにあるexceptionType variableです.この節では詳しく分析します.
ExceptionTypeは、現在のcatchがどのようなタイプの例外を処理できるかを示す例外タイプです.variableは、異常情報を受信するための変数です.プログラムが異常を投げ出すと、エラー情報が含まれているデータが作成され、プログラマはこれらの情報からどのような問題が発生したのか、次にどのように処理するかを判断することができます.
異常はデータである以上、データ型があるはずです.C++は、例外タイプはint、char、float、boolなどの基本タイプであってもよいし、ポインタ、配列、文字列、構造体、クラスなどの集約タイプであってもよいと規定している.C++言語自体および標準ライブラリの関数から放出される例外は、exceptionクラスまたはそのサブクラスの例外です.すなわち、例外が投げ出されると、exceptionクラスまたはそのサブクラスのオブジェクトが作成されます.
ExceptionType variableと関数のパラメータは非常に類似しており、異常が発生すると、異常データはvariableという変数に渡され、これは関数パラメータのプロセスと類似している.もちろん、exceptionTypeタイプに一致する例外データのみがvariableに渡されます.そうしないと、catchはこの例外データを受信したり、catchブロックの文を実行したりしません.すなわちcatchは現在の例外を処理しません.
catchは、異常が発生するとcatchが呼び出され、実パラメータ(異常データ)が受信される戻り値のない関数と見なすことができます.
・しかしcatchと真の関数呼び出しには違いがあります.
・真の関数呼び出しは、パラメータと実パラメータのタイプを一致させるか、自動的に変換することができます.そうしないと、コンパイルフェーズでエラーが発生します.
一方、catchでは、異常は実行段階で発生し、それは任意のタイプであり、事前に予測できないため、コンパイル段階でタイプが正しいかどうかを判断することはできません.プログラムが実行された後、本当に異常を投げ出してから、異常タイプとcatchが処理できるタイプをマッチングし、マッチングに成功すれば現在のcatchを「呼び出す」ことになります.そうでなければ、現在のcatchは無視されます.
総じてcatchは,実際の関数呼び出しと比較して,「実行段階で実パラメータとパラメータをマッチングする」プロセスが1つ増えた.
また、catchが異常データを処理したくない場合は、variableを省略して書くこともできます.
異常が発生すると、プログラムは上から下の順に、異常タイプとcatchが受信できるタイプを1つずつマッチングします.タイプが一致するcatchが見つかったら取得を停止し、現在のcatch処理に異常を渡します(他のcatchは実行されません).最終的に一致するcatchが見つからない場合は、システム処理にのみ渡され、プログラムの実行を終了します.
次の例では、マルチレベルcatchの使用を示します.
実行結果:
catchでは,異常タイプのみが与えられ,異常情報を受信する変数は与えられなかった.
この例では,ベースクラスBaseを定義し,Base派生クラスからDerivedを出した.例外を投げ出すと、Derivedクラスの匿名オブジェクトが作成されます.つまり、例外のタイプはDerivedです.
異常はcatch(Derived)によってキャプチャされることが望ましいが,出力結果から,異常はcatch(Base)によって早期にキャプチャされ,これはcatchが異常タイプにマッチングする際にアップシフト(Upcasting)が発生したことを示す.
catchマッチング中のタイプ変換
C/C++には、一般的な関数(非テンプレート関数)を例にとると、関数呼び出しが発生した場合、実パラメータと形パラメータのタイプが厳密に一致しない場合、実パラメータのタイプが適切に変換され、形パラメータのタイプに適応します.
算数変換:例えばintをfloatに変換し、charをintに変換し、doubleをintに変換するなど.
アップコンバート:つまり派生クラスからベースクラスへの変換です.詳細については、「C++アップコンバート(派生クラスをベースクラスに付与)」をクリックしてください.
const変換:非constタイプもconstタイプに変換されます.たとえば、charをconst charに変換します.
配列または関数ポインタ変換:関数パラメータが参照タイプでない場合、配列名は配列ポインタに変換され、関数名も関数ポインタに変換されます.
ユーザー独自のタイプ変換.
catchは異常タイプにマッチングする過程でもタイプ変換を行うが、この変換はより多くの制限を受け、「アップシフト」、「const変換」、「配列または関数ポインタ変換」しか行えず、その他はcatchに適用できない.
アップシフトは上記の例ですでに発生しており、次の例ではconst変換および配列とポインタの変換を示します.
実行結果:
nums本来のタイプはint[3]であるが、catchには厳密に一致するタイプはないので、まずintに変換し、const intに変換する.
try{
//
}catch(exceptionType variable){
//
}
次の質問はcatchキーワードの後ろにあるexceptionType variableです.この節では詳しく分析します.
ExceptionTypeは、現在のcatchがどのようなタイプの例外を処理できるかを示す例外タイプです.variableは、異常情報を受信するための変数です.プログラムが異常を投げ出すと、エラー情報が含まれているデータが作成され、プログラマはこれらの情報からどのような問題が発生したのか、次にどのように処理するかを判断することができます.
異常はデータである以上、データ型があるはずです.C++は、例外タイプはint、char、float、boolなどの基本タイプであってもよいし、ポインタ、配列、文字列、構造体、クラスなどの集約タイプであってもよいと規定している.C++言語自体および標準ライブラリの関数から放出される例外は、exceptionクラスまたはそのサブクラスの例外です.すなわち、例外が投げ出されると、exceptionクラスまたはそのサブクラスのオブジェクトが作成されます.
ExceptionType variableと関数のパラメータは非常に類似しており、異常が発生すると、異常データはvariableという変数に渡され、これは関数パラメータのプロセスと類似している.もちろん、exceptionTypeタイプに一致する例外データのみがvariableに渡されます.そうしないと、catchはこの例外データを受信したり、catchブロックの文を実行したりしません.すなわちcatchは現在の例外を処理しません.
catchは、異常が発生するとcatchが呼び出され、実パラメータ(異常データ)が受信される戻り値のない関数と見なすことができます.
・しかしcatchと真の関数呼び出しには違いがあります.
・真の関数呼び出しは、パラメータと実パラメータのタイプを一致させるか、自動的に変換することができます.そうしないと、コンパイルフェーズでエラーが発生します.
一方、catchでは、異常は実行段階で発生し、それは任意のタイプであり、事前に予測できないため、コンパイル段階でタイプが正しいかどうかを判断することはできません.プログラムが実行された後、本当に異常を投げ出してから、異常タイプとcatchが処理できるタイプをマッチングし、マッチングに成功すれば現在のcatchを「呼び出す」ことになります.そうでなければ、現在のcatchは無視されます.
総じてcatchは,実際の関数呼び出しと比較して,「実行段階で実パラメータとパラメータをマッチングする」プロセスが1つ増えた.
また、catchが異常データを処理したくない場合は、variableを省略して書くこともできます.
try{
//
}catch(exceptionType){
//
}
catch , 。
catch
, try catch, 。 , try catch:
try{
//
}catch(exception_type_1 e){
//
}catch(exception_type_2 e){
//
}
// catch
catch(exception_type_n e){
//
}
異常が発生すると、プログラムは上から下の順に、異常タイプとcatchが受信できるタイプを1つずつマッチングします.タイプが一致するcatchが見つかったら取得を停止し、現在のcatch処理に異常を渡します(他のcatchは実行されません).最終的に一致するcatchが見つからない場合は、システム処理にのみ渡され、プログラムの実行を終了します.
次の例では、マルチレベルcatchの使用を示します.
#include
#include
usingnamespacestd;
class Base{};
class Derived:publicBase{};
intmain(){
try{
throwDerived();// , Derived
cout<
実行結果:
Exception type: Base
catchでは,異常タイプのみが与えられ,異常情報を受信する変数は与えられなかった.
この例では,ベースクラスBaseを定義し,Base派生クラスからDerivedを出した.例外を投げ出すと、Derivedクラスの匿名オブジェクトが作成されます.つまり、例外のタイプはDerivedです.
異常はcatch(Derived)によってキャプチャされることが望ましいが,出力結果から,異常はcatch(Base)によって早期にキャプチャされ,これはcatchが異常タイプにマッチングする際にアップシフト(Upcasting)が発生したことを示す.
catchマッチング中のタイプ変換
C/C++には、一般的な関数(非テンプレート関数)を例にとると、関数呼び出しが発生した場合、実パラメータと形パラメータのタイプが厳密に一致しない場合、実パラメータのタイプが適切に変換され、形パラメータのタイプに適応します.
算数変換:例えばintをfloatに変換し、charをintに変換し、doubleをintに変換するなど.
アップコンバート:つまり派生クラスからベースクラスへの変換です.詳細については、「C++アップコンバート(派生クラスをベースクラスに付与)」をクリックしてください.
const変換:非constタイプもconstタイプに変換されます.たとえば、charをconst charに変換します.
配列または関数ポインタ変換:関数パラメータが参照タイプでない場合、配列名は配列ポインタに変換され、関数名も関数ポインタに変換されます.
ユーザー独自のタイプ変換.
catchは異常タイプにマッチングする過程でもタイプ変換を行うが、この変換はより多くの制限を受け、「アップシフト」、「const変換」、「配列または関数ポインタ変換」しか行えず、その他はcatchに適用できない.
アップシフトは上記の例ですでに発生しており、次の例ではconst変換および配列とポインタの変換を示します.
#include
usingnamespacestd;
intmain(){
intnums[]={1,2,3};
try{
thrownums;
cout<
実行結果:
Exception type: const int *
nums本来のタイプはint[3]であるが、catchには厳密に一致するタイプはないので、まずintに変換し、const intに変換する.