21

Scott Meyer彼の本では、継承階層を下または横切って安全なキャストを実行するために使用されるEffective C++と述べています。dynamic_castつまり、dynamic_cast を使用して、基本クラス オブジェクトへのポインターまたは参照を、派生または兄弟の基本クラス オブジェクトへのポインターまたは参照にキャストし、キャストが成功したかどうかを判断できるようにします。

失敗したキャストは、null ポインター (ポインターをキャストする場合) または例外 (参照をキャストする場合) によって示されます。

ポインターをキャストし、参照をキャストする場合に失敗したキャストを示す 2 つのコード スニペットを取得したいと思います。

4

3 に答える 3

41

ポインタの場合、これは単純なnullチェックです。

A* a = new A();
B* b = dynamic_cast<B*>(a);

if (b == NULL)
{
    // Cast failed
}

参考までに、次のことを確認できます。

try {
    SomeType &item = dynamic_cast<SomeType&>(obj);
}
catch(const std::bad_cast& e) {
    // Cast failed
}
于 2012-07-16T18:22:10.540 に答える
4

OPのコメント(「スコットが述べたように、キャストがどのように失敗するのかわかりません。」)に基づいて、ここでの本当の質問は、「どのようにdynamic_cast失敗する可能性があるのですか?」のようなものです。

失敗するのは、ターゲット タイプがオブジェクトの動的タイプと一致しない場合です。簡単な例:

struct A {
   virtual ~A() {}
};

class B : public A {};

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

    B *b = dynamic_cast<B *>(a);    // should fail
    if (b == NULL)
        std::cout << "First cast failed.\n";

    A *c = new B;
    b = dynamic_cast<B *>(c);       // should succeed
    if (b == NULL)
        std::cout << "Second cast failed.\n";
    return 0;
}

ここでは type のオブジェクトを指すことがa できBますが、実際には typeのオブジェクトを指していますA。を指すように dynamic_cast を実行しようとするとB、失敗します。2 回目の試行では、タイプ のオブジェクトを指すことができるだけでなく、実際に指すポインターが再び得られますB。するので、この場合は dynamic_cast がB *成功します。

基本的な状況は、参照ケースでは (あまり) 変化せず、ただa,ポインターではなく参照bcなり、例外をキャッチすることで失敗に注意します (@ReedCopsey は、私が持っているとは思えないほど十分に実証しています)。追加する新しいもの)。

于 2012-07-16T18:36:45.947 に答える
4

dynamic_castこれは、ポインターの生成に失敗する可能性があることを示す完全な例です。

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

class B: public A
{
};

class C: public A
{
};

void test()
{
    A a;
    B b;
    A* pA = &b;
    B* pB = dynamic_cast<B*>(pA);  // this works OK, returns the expected pointer
    C* pC = dynamic_cast<C*>(pA);  // this returns NULL because B isn't a C
}

現実の世界では、おそらく作成されたものではないポインタをキャストしようとするでしょうvector。たとえば、.

于 2012-07-16T18:38:17.150 に答える