#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)) {
// ...
}
}
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 )
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.