Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does dynamic_cast work?

If you had the following:

class Animal{};

class Bird : public Animal{};

class Dog : public Animal{};

class Penguin : public Bird{};

class Poodle : public Dog{};

Does dynamic_cast just check if one class is a derived class of another, or if one class is a base class of another? So if I had:

Bird* bird;
Animal* animal;

bird = dynamic_cast<Animal*>(bird);
animal = dynamic_cast<Bird*>(animal);

bird would now point to an Animal class, so that I can use bird->some_function(); and it will call the function in Animal? And animal now points to a Bird class, so I can do animal->some_function(); and it will call some_function(); in Bird?

I've been trying to figure out how the dynamic_cast works, and the resources I've found online haven't been the most helpful. If someone can offer other insight into the functionality of dynamic_cast and some instances in which it would be useful, I'd highly appreciate it.

like image 453
Bob John Avatar asked Dec 09 '12 00:12

Bob John


People also ask

What is the use of dynamic_cast?

The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to a pointer or reference to a class B , where class A is a base class of B .

Should I use dynamic_cast?

This cast is used for handling polymorphism. You only need to use it when you're casting to a derived class. This is exclusively to be used in inheritence when you cast from base class to derived class.

Does dynamic_cast throw?

dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with the cast failing at runtime. The cast will now return the 0 pointer value instead of throwing.

What does dynamic_cast return in C++?

[edit] SyntaxIf the cast is successful, dynamic_cast returns a value of type new-type. If the cast fails and new-type is a pointer type, it returns a null pointer of that type. If the cast fails and new-type is a reference type, it throws an exception that matches a handler of type std::bad_cast.


1 Answers

The most important thing about the dynamic cast is that it should be applied to a polymorphic type. Without that, dynamic cast works like a static cast.

What is a polymorphic type? Any class that has at least one virtual method or virtual destructor or virtual base class is polymorphic. Only those types have a virtual method table (VMT) in their data layout. Classes that do not have anything virtual do not have VMT's. The standard does not say how polymorphism and virtual methods should be implemented, yet all compilers, as far as I know, do this.

In your examples classes are not polymorphic. In my opinion, it would be better if compilers would issue an error when the dynamic cast is applied to a non-polymorphic type. Nevertheless, they do not do this. This adds to the confusion.

VMT pointers for all classes are different. This means that on the runtime looking at:

Animal* animal;

it is possible to know what the real class of the object is. Is it a Bird or a Dog or something else. Knowing the real type from the value of VMT, generated code can make an adjustment if this is needed.

Here is an example:

class Animal   { virtual ~Animal();   int m1; };
class Creature { virtual ~Creature(); int m2; };

class Bird : public Animal, Creature { };

Bird *bird = new Bird();
Creature *creature = dynamic_cast<Creature*>(bird);

Note that creature is not the first base class. This means that the pointer will be shifted to point to the right part of the object. Nevertheless, the following will still be working:

Animal *animal = dynamic_cast<Animal*>(creature);   // Case2.

because VMT of Creature when it is part of other class will not be the same to VMT of the object when it is used stand-alone:

Creature *creature1 = new Creature();

This distinction allows a proper implementation of a dynamic cast. In the example Case2 the pointer will be shifted back. I tested this. This works.

like image 125
Kirill Kobelev Avatar answered Sep 22 '22 01:09

Kirill Kobelev