dynamic_cast fail, but static_cast works

I am trying to use dynamic_cast for this, because it includes RTTI...but it won't work with dynamic_cast, it works with static_cast however
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <string>
#include <memory>

class Base
{
public :
    void println( const std::string& input )
    {
        std::cout << input << ", from base class \n";
    }
};

class Derived : public Base
{
public :
    //override println in the base class
    void println( const std::string& input )
    {
        std::cout << input << ", from derived class \n";
    }
    template< typename T >
    T readln()
    {
        T temp;
        std::cin >> temp;
        return std::move( temp );
    }
};

class notDerived
{
public :
    //override println in the base class
    void println( const std::string& input )
    {
        std::cout << input << ", from derived class \n";
    }
    template< typename T >
    T readln()
    {
        T temp;
        std::cin >> temp;
        return std::move( temp );
    }
};

int main()
{
    Base* derived = new Base;
    derived->println( "hello " );
    if ( Derived* d = dynamic_cast< Derived* >( derived ) )
    {
        int i = d->readln< int >();
        d->println( std::to_string( i ) );
    }
    delete derived;
}

if I change the dynamic_cast to static_cast, this code works like expected. Also, I used new and delete because I thought the problem was that it cannot dynamic_cast a unique_ptr
The dynamic cast fails becase derived isn't pointing to a Derived*.

That can only be determined at runtime in general, and that's why RTTI was introduced to the language (at some cost).

Static cast assumes you know what you're doing, and allows you to override the type system. In this case, you'd be wrong.

A more useful example is when the object type is hidden somehow, and you can't achieve what you want to do using the public interface (of virtual functions).
1
2
3
4
5
6
7
void draw(Shape* obj)
{
    // current implementation only draws things with sides
    if (Polygon* shape = dynamic_cast<Polygon*>(obj)) {
        // ...
    }
}
Last edited on
it won't work with dynamic_cast

dynamic_cast only works if the base class has at least one virtual member function. You probably want the destructor to be virtual, otherwise delete on a base pointer that points to a derived object will not destruct the object correctly.

1
2
Base* ptr = new Derived;
delete ptr; // UB if Base::~Base() is not virtual. 


I used new and delete because I thought the problem was that it cannot dynamic_cast a unique_ptr

You can call get() on the unique_ptr to get a regular pointer that you can then use with dynamic_cast.

1
2
3
4
5
std::unique_ptr<Base> ptr = std::make_unique<Derived>();
if ( Derived* d = dynamic_cast< Derived* >( ptr.get() ) )
{
    ...
}
Haha, yeah thanks...although I already know about the get()
luckily, where I need to use this on, has virtual function( the class is not defined by me )
Hi,

Why create a base class object then want to cast it to derived? Why not create a derived object in the first place? As kbw has already pointed out:

kbw wrote:
A more useful example is when the object type is hidden somehow, and you can't achieve what you want to do using the public interface (of virtual functions).


In other words just use plain virtual polymorphism, for this example?

Remember a pointer to Derived is a valid pointer to Base, this is the most useful concept in polymorphism. Usually I see people wanting to do it the other way around (still wrongly) : cast Derived to Base, but casting is not need at all.

I am not seeing where RTTI is necessary, maybe I have missed something?

Perhaps it's better to mention the actual classes being used rather than a contrived Base/Derived example.
Topic archived. No new replies allowed.