web-dev-qa-db-ja.com

C ++の例外がコンパイラによってチェックされないのはなぜですか?

C++は、チェックされた例外の構文を提供します。次に例を示します。

void G() throw(Exception);
void f() throw();

ただし、Visual C++コンパイラはそれらをチェックしません。スローフラグは単に無視されます。私の意見では、これにより例外機能が使用できなくなります。だから私の質問は: 例外が正しくキャッチ/再スローされるかどうかをコンパイラにチェックさせる方法はありますか? たとえば、Visual C++プラグインまたは別のC++コンパイラ。

PS。コンパイラに例外が正しくキャッチされているかどうかをチェックしてもらいたいのですが、そうしないと、関数呼び出しを行うたびにキャッチを入れなければならない状況になります明示的に何もスローしないと述べていても

更新: Visual C++コンパイラは、throw()でマークされた関数をスローすると警告を表示します。これはすばらしいことですが、残念ながら、スローする可能性のあるサブルーチンを呼び出しても警告は表示されません。例えば:

void f() throw(int) { throw int(13); }
void h() throw() { g(); } //no warning here!
42
Dimitri C.

例外仕様はC++ではまったく役に立ちません。

他の例外がスローされないことは強制されませんが、グローバル関数unexpected()が呼び出されるだけです(設定可能)

例外仕様を使用することは、主に、自分自身(または仲間)を誤った安心感に惑わすことになります。単に気にしないほうがいいです。

32
Pieter

面白いのは、Javaが例外をチェックしていて、Javaプログラマーも例外を嫌っているということです。

C++の例外仕様は、次の3つの理由で役に立ちません。

1。C++例外仕様は最適化を禁止します。

Throw()を除いて、コンパイラーは追加のコードを挿入して、例外をスローしたときに、スタックの巻き戻し中に関数の例外仕様と一致することを確認します。プログラムを遅くする方法。

2。C++例外仕様はコンパイラによって強制されません

コンパイラに関する限り、構文的に正しいのは次のとおりです。

void AStupidFunction() throw()
{
    throw 42;
}

さらに悪いことに、例外仕様に違反した場合、何の役にも立ちません。プログラムが終了します。

。C++例外仕様は関数のシグネチャの一部です。

仮想関数を持つ基本クラスがあり、それをオーバーライドしようとする場合、例外仕様は完全に一致する必要があります。だから、あなたは前もって計画したほうがいいです、そしてそれはまだ苦痛です。

struct A
{
    virtual int value() const throw() {return 10;}
}

struct B : public A
{
    virtual int value() const {return functionThatCanThrow();} // ERROR!
}

例外仕様はこれらの問題を引き起こし、それらを使用することによる利益は最小限です。対照的に、例外仕様を完全に回避すると、コーディングが容易になり、このようなことを回避できます。

40
rlbond

これを見てください:

http://www.gotw.ca/publications/mill22.htm

基本的に例外仕様は実行不可能/使用不可能ですが、それによって例外が機能しなくなるわけではありません。

あなたの質問に関しては、スローされたすべての型がコードのどこかでキャッチされていることをコンパイラにチェックさせる方法はありません。コンパイルユニットがこれを困難にし、ライブラリで使用することを目的としたコードに対してそれを行うことは不可能だと思います(コンパイル時にトップレベルが使用できない場合)。すべてが確実にキャッチされるようにしたい場合は、コードの最上部にcatch(...)を貼り付けます。

15
Patrick

...などの実行前のケースを検出するには.

extern void f() throw (class Mystery);
void g() throw() { 
    f() ; 
}

...静的解析が必要です。はい、コンパイラは多くの静的分析を行っていますが、標準は「スローが一致しない場合はstd :: unexpectedを発生させる」ため、指定子と一致しないオブジェクトをスローするルーチンを作成することは完全に合法です。 、コンパイラの実装者は警告もコメントもしません。

警告サービスを提供すると主張する静的分析ツールには、Gimpel Softwareの lintfor C++ ..が含まれます。

1560キャッチされない例外「名前」が関数「シンボル」のスローリストにありません

そして、 この回答 によると、前の質問に対して QA C++

9

標準がそう言っているからです。例外宣言は、他の例外がスローされないことを意味するものではありません。これは、宣言されていない例外がスローされた場合、nexpected()と呼ばれる特別なグローバル関数が呼び出され、デフォルトでプログラムが終了することを意味します。標準の動作はあまり役に立たないため、通常、関数で例外を宣言することはお勧めしません(空の例外リストを除く)。

8
Tadeusz Kopec

MSVCがインストールされていないかどうかを確認することはできませんが、コンパイラがthrow()仕様を無視していることを本当に確認できますか?

このMSDNページ は、Microsoftがthrow()を認識しており、コンパイラがそれを正しく処理することを期待していることを示しています。まあ、ほとんどの場合、それらがANSI/ISO規格からどのように逸脱しているかについての注記を詳細に参照してください。

編集:しかし、実際には、私はPatrickに同意します。例外仕様はほとんど役に立たない。

0
DevSolar