C++ で扱っている 2 つの継承階層があるとします。1 つはstd::exception
(新しい階層)から継承し、もう 1 つはException
(従来の C++ Builder VCL 基本例外クラス) から継承します。いずれかのタイプの例外をスローする可能性のあるコードを呼び出す場合、次のようなコードを記述する必要があります。
try {
// do stuff....
Function1();
Function2();
} catch (std::exception &ex) {
std::cout << "STL exception caught: " << ex.what() << std::endl;
} catch (Exception &ex) {
std::cout << "Legacy exception caught: " << ex.Message.c_str() << std::endl;
} catch (SomeOtherVendorLibraryException &ex) {
// etc.
}
問題は、C++ には catch-all として使用できる真の強制例外基本クラスがないため、各呼び出し元が最後のすべてのタイプの例外を取得しようとするためにこれらすべての catch 句を持っている必要があることです (例: System.Exception
C# のクラス)。(catch (...)
何をキャッチしたかを知る方法がなく、アクセス違反などの危険なシステム例外もキャッチされる可能性があるため、これはスターターではありません。トラップしない方がよいでしょう。)
これらの「レガシー」例外を階層内のクラスにラップしたいと思いstd::exception
ます。サードパーティの例外を独自の例外システムにラップするというこの概念は、まったく前例のないものではありません。たとえば、.NET Framework は、他のシステム (例: COMException
) の広範なエラー セットをラップします。理想的には、次のようなものを見たいと思っています。
class LegacyException : public std::runtime_error {
public:
// construct STL exception from legacy exception
LegacyException(const Exception &ex) : std::runtime_error(ex.Message.c_str()) {}
};
try {
// In reality, this throw will happen in some function we have no control over.
throw Exception("Throwing legacy exception!");
} catch (std::exception &ex) {
// Ideally, the compiler would use the LegacyException constructor
// to cast the thrown Exception to a LegacyException, which ultimately
// inherits from std::exception.
std::cout << ex.what() << std::endl;
}
当然のことながら、例外がキャッチされることはありません。例外をキャッチするために、コンパイラにかなりの魔法を要求することになります。
レガシー例外をラップするために上記に似たソリューションがあり、これらの目標を達成できますか?
- 1 つの "catch" 句または類似の句。これにより、一般的な例外処理ロジックを 1 回記述するだけで済みます。
- ある例外タイプから別の例外タイプに変換するためのロジックを集中化する必要があります。
- 可能であればマクロを避けます。
- ラムダ関数は使用しません。