web-dev-qa-db-ja.com

参照とポインターでdynamic_castを使用するときの動作の違い

私はdynamic_castの動作をチェックしていて、失敗すると、宛先が参照型の場合にのみstd :: bad_cast例外がスローされることがわかりました。宛先がポインター型の場合、キャストから例外はスローされません。これは私のサンプルコードです:

class A
{
    public:
        virtual ~A()
        {
        }
};

class B : public A
{
};

int  main()
{
    A* p = new A;

    //Using reference
    try
    {
    B& b = dynamic_cast<B&>(*p);
    }
    catch(std::bad_cast exp)
    {
    std::cout<<"Caught bad cast\n";
    }

    //Using pointer
      try
    {
    B* pB = dynamic_cast<B*>(p);

    if( pB == NULL)
    {
        std::cout<<"NULL Pointer\n";
    }
    }
    catch(std::bad_cast exp)
    {
    std::cout<<"Caught bad cast\n";
    }

    return 0;
}

出力は「キャッチされた不良キャスト」と「NULLポインター」です。コードはVS2008を使用してコンパイルされます。これは正しい動作ですか?はいの場合、なぜ違いがあるのですか?

41
Naveen

はい、これは正しい動作です。その理由は、nullポインタは使用できますが、null参照は使用できないためです。参照はオブジェクトにバインドする必要があります。

したがって、ポインタ型のdynamic_castが失敗するとnullポインタが返され、呼び出し元はそれを確認できますが、参照型が失敗するとnull参照を返すことができないため、問題を通知するための唯一の合理的な方法は例外です。

67
sharptooth

C++標準のセクション5.2.7/9を参照してください。

9ポインター型へのキャストの失敗の値は、必要な結果型のNULLポインター値です。参照型へのキャストに失敗すると、bad_cast(18.5.2)がスローされます。

理由について-これらはD&E本のセクション14.2.2からのStroustrupの言葉です:

参照型についての仮定をチェックして、それが私の仮定の誤りであると見なす場合は、参照キャストを使用します。代わりにもっともらしい選択肢の中から選択したい場合は、ポインターキャストを使用して結果をテストします。

26
anon

はい、5.2.7/9

失敗したポインタ型へのキャストの値は、必要な結果型のnullポインタ値です。参照型へのキャストに失敗すると、bad_cast(18.5.2)がスローされます。

8
AProgrammer

はい、そうです。 dynamic_cast失敗した参照キャストに対してNULLを返すことはできません。例外が唯一の方法です。

つまり、参照をNULLにすることはできないため、返すのに適したものはありません。

5
Kim Gräsman