开发者

Why does dynamic cast from class to subclass requires the class to be polymorphic?

As I understand it, what makes dynamic cast different from a static cast is its use of RTTI, and the fact that it fails if the dynamic type of a variable- when casting from base to derived- does not fit. But why does the class have to be polymorphic for that to be done if we have the RTTI anyway?

EDIT: Since there was some confusion about the use of the word "polymorphic", here's the entry in cplusplus.com that prompted me to ask this:

dynamic_cast can be used only with pointers and references to objects. Its purpose is to ensure that the result of the type conversion is a valid complete object of the requested class.

Therefore, dynamic_cast is always successful when we cast a class to one of its base

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 

The second conversion in t开发者_开发百科his piece of code would produce a compilation error since base-to-derived conversions are not allowed with dynamic_cast unless the base class is polymorphic.

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


RTTI information is available only for class with a virtual member. (The assumed implementation is that the vtable contains what it needed for dynamic_cast to work; you could work out other schemes, but all would need a type identifier in the object, so why not use the vptr?)


Run-time type identification is involved. dynamic_cast has to check the validity of down-casting at run-time (and return a NULL pointer / throw an exception if the cast is to an unsuitable type).

The standard states that with polymorphic types, typeid refers to the dynamic type of the object (most derived), for other types it refers to the static type of the object.

I suppose dynamic_cast cannot determine the validity of the down-cast, if the type in question doesn't provide any dynamic type information. With a non-polymorhic Base, a Base* is just that, it doesn't have a dynamic most derived type that can be checked at run-time.

The validity of the up-cast, on the other hand, can be determined statically at compile-time.


What sort of pointer could you use if there was no inheritance relationship? The only legal and sensible casts that can be performed between pointers to objects of different types (ignoring const casts) are within the same inheritance hierarchy.

Edit: To quote BS from the D&E book on dynamic_cast, section 14.2.2.2:

Further, a class with virtual functions is often called a polymorphic class and polymorphic classes are the only ones that can be safely manipulated via a base class ... From a programming point of view, it therefore seems natural to provide RTTI for polymorphic types only.

My emphasis.


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;

}

The Base class has to have at the very least a virtual destructor. Not declaring a virtual destructor may introduce memory leaks because the Derived destructor will not be called.

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

If RTTI is switched on, this line of code will result in a null pointer. If RTTI is not enabled the line results in a runtime error.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜