2

私が理解しているように、動的キャストが静的キャストと異なるのは、RTTI の使用と、変数の動的型 (ベースから派生型へのキャスト時) が適合しない場合に失敗するという事実です。しかし、とにかく RTTI があるのに、なぜそれを行うためにクラスをポリモーフィックにする必要があるのでしょうか?

編集:「ポリモーフィック」という言葉の使用について混乱があったため、cplusplus.com のエントリを次に示します。

dynamic_cast は、オブジェクトへのポインターと参照でのみ使用できます。その目的は、型変換の結果が要求されたクラスの有効な完全なオブジェクトであることを確認することです。

したがって、クラスをそのベースの 1 つにキャストすると、dynamic_cast は常に成功します。

classes: class CBase { };
class CDerived: public CBase { };

CBase b; CBase* pb; CDerived d;
CDerived* pd;

pb = dynamic_cast<CBase*>(&d);     //ok: derived-to-base 
pd = dynamic_cast<CDerived*>(&b);  //wrong: base-to-derived 

基本クラスがポリモーフィックでない限り、基本クラスから派生クラスへの変換は dynamic_cast では許可されないため、このコードの 2 番目の変換ではコンパイル エラーが発生します。

http://www.cplusplus.com/doc/tutorial/typecasting/

4

4 に答える 4

7

RTTI 情報は、仮想メンバーを持つクラスでのみ使用できます。(想定される実装は、vtable には dynamic_cast が機能するために必要なものが含まれているというものです。他のスキームを作成することもできますが、すべてオブジェクトに型識別子が必要になるため、vptr を使用しないのはなぜですか?)

于 2010-02-09T13:38:52.010 に答える
2

実行時の型識別が含まれます。dynamic_cast実行時にダウンキャストの有効性をチェックする必要があります (そして、NULL ポインターを返すか、キャストが不適切な型への場合は例外をスローします)。

標準では、多相型の場合、typeid はオブジェクトの動的な型 (最も派生したもの) を参照し、他の型の場合はオブジェクトの静的な型を参照すると述べています。

問題の型が動的型情報を提供しない場合、dynamic _cast はダウンキャストの有効性を判断できないと思います。非ポリモーリック Base では、aは実行時にチェックできる動的な最も派生した型を持たないということです。Base*

一方、アップキャストの有効性は、コンパイル時に静的に決定できます。

于 2010-02-09T14:08:40.210 に答える
1

継承関係がない場合、どのようなポインターを使用できますか? 異なる型のオブジェクトへのポインター間で (const キャストを無視して) 実行できる唯一の正当で適切なキャストは、同じ継承階層内にあります。

編集: D&E ブックの BS を引用するにはdynamic_cast、セクション 14.2.2.2:

さらに、仮想関数を持つクラスは多態性クラスと呼ばれることが多く、基底クラスを介して安全に操作できるのは多態性クラスだけ です...プログラミングの観点からは、多態性型のみに RTTI を提供するのが自然に思えます。 .

私の強調。

于 2010-02-09T13:40:08.917 に答える
0
class Base
{
public:
    virtual ~Base()
    {
        std::cout << "Base" << std::endl;
    }
};

class Derived : public Base
{
public:
    ~Derived() 
    {
        std::cout << "Derived" << std::endl;
    }
};

int main()
{

    Base b; Base* pb; Derived d; 
    Derived* pd;
    Derived* thisWillBeNull = 0;
    Base *pBase = new Derived();

    pb = dynamic_cast<Base*>(&d);     //ok: derived-to-base  
    thisWillBeNull = dynamic_cast<Derived*>(&b);  //null 

    pd = dynamic_cast<Derived*>(pDerived);  

delete pDerived;

return 0;

}

基本クラスには、少なくとも仮想デストラクタが必要です。仮想デストラクタを宣言しないと、派生デストラクタが呼び出されないため、メモリ リークが発生する可能性があります。

thisWillBeNull = dynamic_cast<Derived*>(&b);  

RTTI がオンになっている場合、このコード行は null ポインターになります。RTTI が有効になっていない場合、行は実行時エラーになります。

于 2010-02-09T15:02:06.957 に答える