11

C++ で例外処理を学習していて、問題が発生しました。コードは次のとおりです。

#include<iostream>
#include<exception>

using namespace std;

class A
{
public:
    virtual void f(void){}
};

class AA:public A
{
public:
    void aa(void){};

};

int main(void)
{

    A a;
    try
    {
        dynamic_cast<AA>(a).aa();
    }
    catch(exception ex)
    {
        cout<<"["<<ex.what()<<"]"<<endl;
    }
    return 0;
}

したがって、try catch を使用すると、関数を実行して例外の内容を表示できると思いましたが、コンパイラはそれをコンパイルしません。GNU GCC でコードブロックを使用しています。コードを意図したとおりに実行するために必要なことを教えてください。どうもありがとう。

4

4 に答える 4

18

dynamic_castポインター値または参照にのみキャストできます。これはまさにエラーが伝えていることです。

C++ 標準の $5.2.7/1 から。

式 dynamic_cast< T >(v) の結果は、式 v を型 T に変換した結果です。T は、完全なクラス型へのポインターまたは参照、または「cv void へのポインター」でなければなりません。</p>

dynamic_castオブジェクトを変換できないときに例外をスローするには、参照にキャストする必要があります。次のように変更します。

dynamic_cast<AA&>(a).aa();
//           ^^^ cast to reference.

Johnsywebが指摘したように、変換が失敗するdynamic_castと常にスローされます。から派生してstd::bad_castいますが、予想される失敗条件に最も適した例外を使用することを常にお勧めします。これにより、他のエラーが誤ってキャストの失敗として解釈されるのを防ぐことができます。std::bad_caststd::exception

これを例に適用すると、以下のコードのようになります。

#include <iostream>
#include <typeinfo> // std::bad_cast

class A
{
public:
    virtual void f(void){}
};

class AA:public A
{
public:
    void aa(void){};
};

int main(void)
{
    A a;

    try
    {
        dynamic_cast<AA&>(a).aa();
    }
    catch(const std::bad_cast& ex)
    {
        std::cout << "["<<ex.what()<<"]" << std::endl;
    }
    return 0;
}

[次のようなことを行うことusing namespace std;は、グローバル名前空間の識別子と競合する可能性があるため、強くお勧めしません。上記の例では削除しています。]

于 2013-06-16T02:56:23.227 に答える
5

あなたの問題は例外処理ではなく、動的キャストにあります:

'AA' is not a reference or pointer

dynamic_castポインタ参照インスタンスclassではなく esに安全に変換します。

したがって、次のことができます。

dynamic_cast<AA&>(a).aa();

...これは常に失敗し、std::bad_cast例外がスローされます。

exception期待している最も具体的なタイプをキャッチする必要があります。推奨される方法catchは参照によるものであるため、次のことをお勧めします。

catch (std::bad_cast const& ex)

詳細情報: cppreference.com のdynamic_cast変換

于 2013-06-16T02:57:16.650 に答える
4

dynamic_castポインタまたは参照上にないため、コンパイラ エラーが発生しています。
次のように変更します。

dynamic_cast<AA&>(a).aa();

...そして、適切な例外がスローされます。

補足: g++ のようなスマート コンパイラも同様に警告します:
warning: dynamic_caston an object (here a) can never success .

したがって、そのようなコードをいじるために制限することをお勧めします。製品品質のコードでは、dynamic_castポインター/参照に対してのみ実行する必要があります。

于 2013-06-16T02:56:07.290 に答える
4

同じエラーに対処しましたが、私の場合はポインターからポインターに移動していたため、ここでの他の回答は当てはまりませんでした。ただし、私のエラー メッセージは少し異なりerror: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type)ました。

私の場合の根本的な原因は、はるかに単純でありふれたものでした。

最後にto complete タイプが追加されていることに注意してください。これにより、使用していたクラスのヘッダー ファイルをインクルードしていなかったことを思い出しました。A*ヘッダーファイルで前方宣言されていたため、不明なシンボルではなく、class A;存在するが完全ではないため、エラーが発生しました。

私の場合の解決策は、キャスト先のクラスのヘッダー ファイルをインクルードすることでした。

これは上記の質問者の問題ではありませんが、私のケースからわかるように、同じタイプのエラーが発生する可能性があります。

于 2016-08-16T18:50:57.737 に答える