2017-09-02 15 views
6

私は初心者ですので、この愚かな質問のためにお詫び申し上げます。私はstackoverflowで同様の答えを見つけることができないので、私はここにそれを掲示しています。カスタム例外のメソッド/コンストラクタシグネチャにthrow()がある場合とない場合

私はC++で例外を進行して、私はカスタム例外を除いて、上のいくつかの手をしていたとして、私は上記のコードは、教師によって示された、このコード

class MyException: public std::exception{ 
public: 
    virtual const char* what() const throw() { 
     return "something bad happened"; 
    } 

}; 

// class that throws above exception 

class canGoWrong { 
public: 
    canGoWrong(){ 
     throw MyException(); 
    } 
}; 

を持っています。コンストラクタは、基本クラスexceptionで定義された仮想関数を実装しました。私はそこまでたどり着いた。

私は別のバージョンを練習しようとしていましたが、仮想を再定義する代わりにカスタム関数を使用しようとしました(C++はインターフェイスのコンセプトを厳密には実施しません。 。)

私は両方の方法で動作の違いを見つけることができませんでしたが、要約すると

class my_custom_shit_exception: public std::exception { 
public: 
    const char* show() { // I omitted the const throw() here 
      return "This is an error encountered\n"; 
    } 
}; 

class myclass { 
public: 
    myclass() { 
     throw my_custom_shit_exception(); 
    } 
}; 

としてそれを書いた

public: 
const char* show() { 
     return "This is an error encountered\n"; 
} 
virtual const char* what() const throw() { 
    return "something bad happened"; 
} 
  • なぜconst throw()what()仮想機能で使用されましたか?どのような違いがありますか?

ありがとうございます。

+3

"C++は厳密にインターフェイスの概念を強制していないため、"あなたが意図したものなら、それは純粋仮想関数用です。 – tkausl

+1

あなたが省略したthrow()は '例外仕様'です。コンパイラに関数が例外をスローしないこと、 'what()'関数、つまりこれを強制するとは言いません。わかりやすくするために、例外仕様を読んでください。 –

+1

非常に興味深い質問です。それは同じ質問ではありませんが、私は[これは役に立つ]と思う(https://stackoverflow.com/questions/5230463/what-does-this-function-declaration-mean-in-c) – user1754322

答えて

3

関数シグネチャ

class std::exception { 
    //... 
public: 
    virtual const char* what() const throw(); 
    //... 
}; 

として読み取ることができる:whatは、一定文字(列)へのポインタを返し、従って(そのオブジェクトのメンバーを変更しないstd::exceptionの仮想メンバー関数であります2nd const)、コード内に例外をスローしないことを保証します。

例外仕様は現在廃止されているので注意してください。代わりに、C++ 11では例外をスローしないように "保証する"関数を宣言するためのnoexcept指定があります。さらに、C++ 17 throw()noexcept(true)の同義語となっていますが、動作が少し異なります。

this descriptionnoexceptを参照してください。

また、関数のnoexcept指定はコンパイル時のチェックではなく、関数が例外をスローするかどうかをコンパイラに知らせるためのメソッドに過ぎないことに注意してください。この情報を使用して、非投げ込み関数[...]の特定の最適化を有効にします。

+0

ありがとうございます@キング・スリルビート。私は '例外を投げないことを保証する 'という最後の部分には疑問がある。カスタム例外クラスを 'virtual const char * what()const throw(){ char * pMemory = new char [999999999999999];' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''例外をスローしないことが保証されているという意味ですか? – file2cable

+1

@ file2cable @ cppreferenceへのリンクを参照してください私は私の答えに入れました:これはページの真ん中近くの例です:要約すると、例外がスローされ、 'std :: terminate'を呼び出す結果となり、プログラムを中止します別の終了ハンドラを指定しなかった場合)。 –

4

私はこれがdoSomethingのが例外をスローすることはありませんと言うことはありませんスコット・マイヤーズ

「効果的なC++」第三版

int doSomething() throw(); // note empty exception spec.

からいくつかの引用符を見せたかったです。 は、doSomethingが例外をスローすると、それは重大なエラーであり、 であり、予期しない関数を呼び出すべきだと言います。†

予期しない機能については、お好きな検索エンジンまたは 包括的なC++テキストを参照してください。 (おそらく、予期しない関数を指定set_unexpected、 機能を探して、より良い運を持っています。)

そして、 "効果的な現代のC++" C++ 11では

、無条件noexceptから例外のためのもので、例外を出さないことを保証しています。

実行時に例外がfから離れる場合、fの例外仕様は違反されます。 C++ 98の例外仕様では、呼び出しスタックはfの呼び出し元に戻され、ここでは何も処理されていない アクションが終了すると、プログラムの実行が終了します。 C++ 11の例外仕様では、実行時の動作はわずかに異なります。プログラムの実行が終了する前に、スタックはおそらく の巻き戻しのみになります。 コールスタックの巻き戻しと巻き戻しの違いは、コード生成に驚くほど大きな影響を与えます。 noexcept関数では、オプティマイザは、例外が を関数から伝播し、noexcept関数のオブジェクトが構造の逆順で破棄されることを保証しなければならない場合は、 が実行不可能な状態にならないようにする必要があります機能を残す。 "throw()"例外仕様の関数では、このような最適化の柔軟性がなく、例外仕様のない関数として がありません。

関連する問題