tags:

views:

169

answers:

4

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 this 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/

+6  A: 

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?)

AProgrammer
Depends what you mean by RTTI - you can call typeid() on any object.
anon
@Neil, If the object is not of a polymorphic class type, the result represents the static type of the object, not the dynamic type. I would not call that RTTI and it is useless for dynamic_cast.
AProgrammer
thats exactly how I'd do it if I was implementing runtime type checking.there is generally a vtable per class with virtual members, so the address could be used as type.if there is no vtable, there is no information on what the random block of data being pointed to is! there is no internal type or size stored.(i've never used dynamic cast in my life, I don't know why people are so interested in it)
matt
+1  A: 

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.

anon
Nonono.... I'm not talking about polymorphism in the inheritance relation sense of the word. A polymorphic class in C++ means that it has a virtual method. http://www.geekinterview.com/question_details/51645
EpsilonVector
@EpsilonVector Strangely enough, I do know that - what's your point?
anon
You can have an inheritance relationship without virtual members in the base class. That happens quite often naturally with mix-ins and the CRTP.
AProgrammer
@Neil That apparently dynamic_cast from base to derived requires for the class to have a virtual method, and I was wondering about the reason for that requirement.
EpsilonVector
@EpsilonVector Please see my edited answer.
anon
+1  A: 

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.

UncleBens
A: 
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.

Laureano