9

dynamic_casts は低速で​​すが、s よりも安全ですstatic_cast(もちろん、オブジェクト階層で使用する場合)。私の質問は、デバッグ コードですべての (動的) キャストが正しいことを確認した後、それらをstatic_casts に変更しない理由はありますか?

次の構成でこれを行う予定です。(ところで、より良い名前を思いつくことができますassert_castか? 多分debug_cast?)

#if defined(NDEBUG)

    template<typename T, typename U>
    T assert_cast(U other) {
        return static_cast<T>(other);
    }

#else

    template<typename T, typename U>
    T assert_cast(U other) {
        return dynamic_cast<T>(other);
    }

#endif

編集: Boost には既にこのための何かがあります: polymorphic_downcast. それを指摘してくれたPlasmaHHに感謝します。

4

5 に答える 5

4

いいえ!dynamic_castキャストだけではありません。オブジェクトの実行時タイプをチェックできます。ただし、コンパイラには不明であるが、実行時にのみ認識される階層をトラバースすることもできます。static_castそれはできない。

例えば:

class A1
{ 
    virtual ~A1() {} 
};
class A2
{
    virtual ~A2() {} 
};

class B : public A1, public A2
{ };

A1 *a1 = new B;
A2 *a2 = dynamic_cast<A2*>(a1); //no static_cast!

A1 *x = ...;
if (B *b = dynamic_cast<B*>(x)) //no static_cast!
  /*...*/; 
于 2011-09-09T09:46:49.420 に答える
2

dynamic_cast成功したことをアサートする必要があります。

template<typename T, typename U>
T *assert_cast(U *other) {
    T *t = dynamic_cast<T>(other);
    assert(t);
    return t;
}

dynamic_castそれらが同等であると確信している状況で置き換えるstatic_castことは、常にnullではないことが確実なポインターのnullチェックを削除することと同じです。パフォーマンス上の理由から、これを行うことができます。

于 2011-09-09T09:44:13.373 に答える
2

実行時の要因/変数/入力のすべての可能な組み合わせでテストした限り、確かに。コメントで述べたように、これはアサーションの削除に似ています。

キャストが常に正しいという必要な保証があれば、これを本質的に危険にする言語はありません。ただし、そのような保証を行うことはおそらくできないという点で、本質的に安全ではないと感じます.


アップデート

Konstantin は、多重継承を処理する場合、この手法は継承ツリーを 1 ステップ上/下に移動する場合にのみ機能することを証明しました1

struct A1 { virtual ~A1() {} };
struct A2 { virtual ~A2() {} };
struct A3 { virtual ~A3() {} };

struct B : A1, A2 {};
struct C : A1, A3, A2 {};

int main() {
    A1* a1 = (rand() < RAND_MAX / 2 ? (A1*)new B : (A1*)new C);

    A2* p1 = dynamic_cast<A2*>(a1);
    // ^ succeeds, but is a cross-cast

    // A2* p2 = static_cast<A2*>(a1);
    // ^ ill-formed

    A2* p3 = static_cast<A2*>(static_cast<B*>(a1));
    // ^ must chain, instead.
    // but p3 is invalid because we never
    //   checked that `dynamic_cast<B*>(a1)` is valid.. and it's not

    // Instead, let's expand the `dynamic_cast`s into a chain, too:
    A2* p3 = dynamic_cast<B*>(a1);
    A2* p4 = dynamic_cast<A2>*(a1);
    // ^ p3 fails, so we know that we cannot use `static_cast` here
}

dynamic_castしたがって、 s をstatic_casts iffに置き換えることができます。

  • それぞれが1 つのステップ アップまたはダウンdynamic_castのみを実行します。
  • それぞれdynamic_castが常に成功することが知られています。

1実際には、たとえば、ダウンキャストは任意の数のステップで機能するため、これは少し単純化されています。しかし、それは良い経験則になります。

于 2011-09-09T09:45:23.863 に答える
1

プロジェクトにもよると思います。原子力発電所の管理ソフトウェアなら安全を好み、3Dゲームならパフォーマンスを好みます。dynamic_cast本番コードですべてが正しいことを確信することはできません。安全性よりもパフォーマンスが重要な場合は、取り外してください。

于 2011-09-09T09:47:25.180 に答える
1

デバッグ コードですべての (動的) キャストが正しいことを確認した後、それらを static_casts に変更しない理由はありますか?

私見、すべて dynamic_cast<>が正しいと100%確信している場合、それらをに変更しない理由static_cast<>はありません。それらは変更できます。

于 2011-09-09T09:48:56.880 に答える