web-dev-qa-db-ja.com

違い:std :: runtime_error vs std :: exception()

違いは何ですか std::runtime_errorおよびstd::exception?それぞれの適切な用途は何ですか?そもそもなぜ違うのですか?

115
sivabudh

_std::exception_は、例外階層で基本クラスとして機能することが唯一の目的であるクラスです。他の用途はありません。つまり、概念的にはabstractクラスです(C++の用語の意味で抽象クラスとして定義されていない場合でも)。

_std::runtime_error_は、さまざまなruntimeエラーが発生した場合にスローされることを意図した、_std::exception_から派生したより特殊なクラスです。二重の目的があります。単独でスローすることも、_std::range_error_、_std::overflow_error_など、さらに特殊なタイプのランタイムエラー例外の基本クラスとして機能することもできます。 _std::runtime_error_、および_std::exception_から派生した独自の例外クラスを定義できます。

_std::runtime_error_と同様に、標準ライブラリには_std::logic_error_が含まれており、これも_std::exception_から派生しています。

この階層を持つことのポイントは、C++例外処理メカニズムの全機能を使用する機会をユーザーに与えることです。 「catch」句は多態性例外をキャッチできるため、ユーザーは例外階層の特定のサブツリーから例外タイプをキャッチできる「catch」句を作成できます。たとえば、catch (std::runtime_error& e)は、_std::runtime_error_サブツリーからのすべての例外をキャッチし、他のすべてをパススルーさせます(さらに呼び出しスタックをさらに上に飛ばします)。

追伸有用な例外クラス階層(コードの各ポイントで関心のある例外タイプのみをキャッチできるようにする)を設計するのは簡単なことではありません。標準C++ライブラリで見られるものは、言語の作成者によって提供される1つの可能なアプローチです。ご覧のように、彼らはすべての例外タイプを「実行時エラー」と「論理エラー」に分割し、そこから独自の例外タイプを進めることにしました。もちろん、その階層を構成する別の方法がありますが、これは設計でより適切な場合があります。

更新:Portability Linux vs Windows

Loki Astariとunixman83が以下の回答とコメントで述べたように、exceptionクラスのコンストラクターはC++標準に従って引数を取りません。 Microsoft C++には、exceptionクラスの引数を取るコンストラクタがありますが、これは標準ではありません。 _runtime_error_クラスには、WindowsとLinuxの両方のプラットフォームで引数(_char*_)をとるコンストラクターがあります。移植性を高めるには、_runtime_error_を使用する方が適切です。

(そして、プロジェクトの仕様がコードをLinux上で実行する必要がないと言っているからといって、Linux上で実行する必要がないという意味ではないことを忘れないでください。)

147
AnT

std :: exceptionは、標準の例外階層の抽象ベースと見なされる(考慮されることに注意)必要があります。これは、特定のメッセージを渡すメカニズムがないためです(これを行うには、what()を派生および特殊化する必要があります)。 std :: exceptionの使用を止めることは何もありません。また、単純なアプリケーションの場合は、必要なものはすべて揃っています。

一方、std :: runtime_errorには、文字列をメッセージとして受け入れる有効なコンストラクターがあります。 what()が呼び出されると、コンストラクターに渡された文字列と同じ文字列を持つC文字列を指すconst charポインターが返されます。

try
{
    if (badThingHappened)
    {
         throw std::runtime_error("Something Bad happened here");
    }
}
catch(std::exception const& e)
{
    std::cout << "Exception: " << e.what() << "\n";
} 
18
Martin York