2016-11-20 10 views
4

C++標準ライブラリは、std :: runtime_errorなどを定義してstd :: exceptionから継承しますが、継承は仮想ではありません。これは、例外階層の拡張を複雑にします。たとえば、次のコードには問題があります。なぜC++標準ライブラリは例外の仮想継承を使用しませんか?

class sql_exception : public virtual std::exception {...}; 
class sql_disconnected : public virtual std::runtime_error, public virtual sql_exception {...}; 
void do_something() { 
    throw sql_disconnected(); 
} 
void call_something() { 
    try { 
    do_something(); 
    } catch (const std::exception& e) { 
    } 
} 

std :: exceptionは、IMHOとして認識されていません。これは様々な(不必要に複雑な[IMHO])方法で回避することができます。

標準ではこの動作が許されるべきだと思うし、「標準であるため標準だ」以外の理由があると私は想定していないからだ。

私は、仮想継承に関連するコストがあることを認識していますが、AFAIKはスタックの巻き戻しのコストとそれ以外の例外処理のコストと比較して無視できます。

Q1:何のために技術的な理由標準ライブラリでこの動作を実装しましたか?

Q2:階層を拡張する問題がありましたか?その場合、その標準についてトピックについて何が言いますか?スタンダードはそれを妨げているのか、あるいはそれに従うように勧告していますか?

+0

例から、仮想継承が必要な理由は不明です。 – Jarod42

+0

@darod42仮想継承は、std :: exceptionが捕捉されるように例外クラスがダイヤモンドの継承パターンを解決するために推奨/必要です.std :: runtime_errorとsql_exceptionの両方がstd :: exceptionから継承し、仮想継承なしでどのstd :: exception baseが2つあるので意味が分からない。 – Martin

+2

'sql_disconnected'を' std :: runtime_error'から継承するのはなぜですか? –

答えて

2

sql_disconnectedstd::runtime_errorから派生させることは意味がありませんが、同じからsql_exceptionを得ることはできません。 IMHOのSQLエラーは、ランタイムエラーとして扱う必要があります。 std::runtime_errorstd::exceptionから派生しているため、最初にダイヤモンド階層を作成する必要はないため、仮想継承を使用してその問題を解決する必要はありません。標準的なSTL例外のどれも仮想継承を使用せず、カスタム例外もどちらも使用しないでください。

class sql_exception : public std::runtime_error {...}; 
class sql_disconnected : public sql_exception {...}; 

void do_something() { 
    throw sql_disconnected(); 
} 

void call_something() { 
    try { 
    do_something(); 
    } 
    catch (const std::exception& e) { 
    } 
} 
+1

これは質問に対する答えではありません。あなたの質問に付随する例が可能な最良の例ではない理由を説明してください。問題はC++の標準ライブラリであり、それを説明するためのサンプルコードではありません。 – Giel

関連する問題