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


127

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

回答:


152

std::exception例外階層の基本クラスとして機能することのみを目的とするクラスです。他の用途はありません。つまり、概念的には抽象クラスです(C ++の用語で抽象クラスとして定義されていなくても)。

std::runtime_errorは、std::exceptionさまざまなランタイムエラーが発生した場合にスローされるように設計された、より特殊なクラスです。それは二重の目的を持っています。それはそれ自体でスローすることができ、またはそれは、次のようなランタイムエラー例外の様々な、より専門種類、に基本クラスとして機能することができstd::range_errorstd::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サブツリーからすべての例外をキャッチし、他のすべての例外を通過させます(さらに呼び出しスタックを上に飛ぶ)。

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

更新:移植性LinuxとWindows

Loki Astariとunixman83が以下の回答とコメントで述べているように、exceptionクラスのコンストラクターはC ++標準に従って引数を取りません。Microsoft C ++には、exceptionクラスの引数を取るコンストラクターがありますが、これは標準ではありません。このruntime_errorクラスにはchar*、WindowsとLinuxの両方のプラットフォームで引数()を取るコンストラクターがあります。持ち運びできるようにするために、より適切に使用してくださいruntime_error

(そして、プロジェクトの仕様に、コードをLinuxで実行する必要がないと記載されているからといって、Linuxで実行する必要がないという意味ではありません。)


1
ありがとうございました。素晴らしい答え。ただし、別の種類の例外が必要かどうかは疑問に思っています。
sivabudh 2009年

1
例外を回復できる可能性がある場合は、例外処理メカニズムを使用して例外をハンドラーに転送し、問題を修正することができるため、別のタイプの例外が役立ちます。回復の可能性がない場合は、標準の例外のいずれかで問題ありません。
Martin Yorkの

1
余談ですが、からの派生を強制するルールはどこにもありませんstd::exception。もちろん、そのすべてのstd派生クラスがスローされますが、std::exception派生オブジェクトのみをスローする理由はまったくありません。
rubenvb 2014年

1
@rubenvb私はそれについて知りませんでしたが、例外から派生したクラスのオブジェクトのみがスローされた場合、将来のメンテナンスのためにコードを明確にするでしょう。例:コードベースに実装されているカスタム例外を見つけ、例外から派生したクラスを検索したい。
this.myself 2014年

21

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

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

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

1
答えマーティンをありがとう。ただし、上記と同じ方法でstd :: exception()を使用します。つまり、std :: exception()コンストラクタは、std :: string()またはconst char *も使用できます。
sivabudh 2009年

14
規格に従っていない。std :: exceptionには、引数を取らないコンストラクタが1つあります。std :: stringまたはC-Stringを受け入れるバージョンの使用は移植できません。
マーティンヨーク

10
マイクロソフトのおかげで、私は投げに慣れましたstd::exception(std::string)std::runtime_error私は自分のコードをLinux(GCC)で機能させたい場合はスローする必要があることを理解しました。
unixman83 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.