My situation is similar to dynamic_cast<B *> (&a) gives a warning.
I have one base and one derived class:
struct Base {
virtual ~Base() = default;
int foo() { return 5; }
};
struct Derived : public Base {
int bar() { return 10; }
};
I have typed unit test which checks that foo() returns 5 for both Base and Derived classes and bar() returns 10 for Derived class.
...
using Types = ::testing::Types(Base, Derived);
TYPED_TEST(Foo, Bar){
auto obj = std::make_unique<ParamType>();
auto *derived = dynamic_cast<Derived*>(obj.get());
// check logic for Base
// check logic for Derived if derived != nullptr
}
After test instantiation with ParamType equals Base, the line with dynamic_cast produces warning about dynamic_cast is never succeeds, as it is supposed to be.
How can I disable this warning on gcc compiler?
You might use if constexpr, something along:
TYPED_TEST(Foo, Bar){
auto obj = std::make_unique<ParamType>();
// TestBase(*obj);
if constexpr(std::is_same_v<ParamType, Derived>) {
// auto *derived = dynamic_cast<Derived*>(obj.get()); // No longer needed
// TestDerived(*obj);
}
}
Related
Why this code is valid in C++:
class Base
{
public:
Base() = default;
// base class stuff...
};
template<typename NumericType>
class Numeric : public Base
{
public:
Numeric() : m_value() {}
void setValue(NumericType value) { m_value = value; }
NumericType value() const { return m_value; }
private:
NumericType m_value;
};
int main()
{
auto integerPtr = new Numeric<int>();
Base *basePtr = integerPtr;
if (auto doublePtr = static_cast<Numeric<double>*>(basePtr)) {
doublePtr->setValue(6543423.634234);
std::cout << "Wow: " << doublePtr->value() << std::endl;
}
return 0;
}
To be honest, I was expecting compilation errors or at least that static_cast will fail but, this code example compiles, runs, and even works correctly.
Compiled with MCVS2019 32bit.
See static_cast from cppreference:
If new_type is a reference or pointer to some class D and expression is lvalue of its non-virtual base B or prvalue pointer to it, static_cast performs a downcast. (This downcast is ill-formed if B is ambiguous, inaccessible, or virtual base (or a base of a virtual base) of D.) Such a downcast makes no runtime checks to ensure that the object's runtime type is actually D, and may only be used safely if this precondition is guaranteed by other means, such as when implementing static polymorphism. Safe downcast may be done with dynamic_cast.
Your code invokes undefined behavior, because the cast is ill-formed. You should use dynamic_cast for up/downcasts. Provide a virtual destructor in Base then this code:
#include <iostream>
class Base
{
public:
Base() = default;
virtual ~Base() = default;
};
template<typename NumericType>
class Numeric : public Base
{
public:
Numeric() : m_value() {}
void setValue(NumericType value) { m_value = value; }
NumericType value() const { return m_value; }
private:
NumericType m_value;
};
int main()
{
auto integerPtr = new Numeric<int>();
Base *basePtr = integerPtr;
if (auto doublePtr = dynamic_cast<Numeric<double>*>(basePtr)) {
doublePtr->setValue(6543423.634234);
std::cout << "Wow: " << doublePtr->value() << std::endl;
}
return 0;
}
Is correct and produces no output as expected.
Why this code is valid in C++
It is not valid code. Remember that incorrect code does not necessarily produce compiler errors. Anything can happen when your code has undefined behavior.
PS: I would have expected your code to blow up when optimizations are turned on. To my surprise, it still appears to work (https://godbolt.org/z/czfobbfqo). Thats the nasty side of undefined behavior. It may go unnoticed and will only blow up once you shipped the code and make a demo in front of your customers ;).
In our legacy project we have a function that takes reference to a base class and creates a copy of the derived class on the heap. This is solved essentially like this: https://godbolt.org/z/9ooM4x
#include <iostream>
class Base
{
public:
virtual Base* vclone() const = 0;
int a{7};
};
class Derived : public Base
{
public:
Derived()
{
a = 8;
}
Base* vclone() const override
{
return new Derived(*this);
}
};
Base* clone(const Base& original)
{
return original.vclone();
}
int main()
{
Derived d1;;
auto* d2 = clone(d1);
std::cout << d2->a << std::endl;
}
This works, but I would like to get rid of the boilerplate vclone method that we have to have in every single derived class.
We have hundreds of derived classes, some of them derived not directly from Base, but from some of the other derived classes too. So if we forget to override the vclone method, we may not even get a warning of the slicing that will happen.
Now, there is much to say about such a design, but this is 10-15 year old code that I try to modernize step by step. What I do look for, is a templatized version of clone that does not depend on a virtual method. What I want, is a clone function like this:
Base* clone(const Base& original)
{
return new <Actual Derived Type>(original);
}
The actual derived type is somewhat known, since a dynamic_cast will fail if trying to cast to it with wrong type, but I don't know if it is possible to access the actual type in a way that I want.
Any help would be appreciated.
I also think you probably cannot improve the code in the sense to make it shorter.
I would say this implementation is basically the way to go.
What you could do is to change the return value of Derived::clone to Derived *. Yes C++ allows this.
Then a direct use of Derived::clone yields the correct pointer type and Base::clone still works as expected
class Derived : public Base
{
public:
Derived()
{
a = 8;
}
Derived* vclone() const override // <<--- 'Derived' instead of 'Base'.
{
return new Derived(*this);
}
};
I would also rename to vclone member function to clone (There is no need to have two names).
The free function clone could be made a template so that it works for all classes and returns the right pointer type
template <class T>
T *clone(const T *cls)
{
return cls->clone();
}
However, all these changes do not make the code shorter, just more usable and perhaps more readable.
To make it a little shorter you might use an CRTP approach.
template <class Derived, class Base>
class CloneHelper: public Base {
Derived* vclone() const override
{
return new Derived(* static_cast<Derived *>(this) );
}
};
// then use
class Derived : public CloneHelper<Derived, Base>
{
public:
Derived()
{
a = 8;
}
};
However, I am not sure if it is worth it. One still must not forget the CloneHelper, it makes inheritance always public and you cannot delegate to the Base constructor so easily and it is less explicit.
You could use an outside clone function and typeid:
#include <typeindex>
#include <string>
#include <stdexcept>
#include <cassert>
template<class Derived_t, class Base_t>
Base_t *clone_helper(Base_t *b) {
return new Derived_t(*static_cast<Derived_t *>(b));
}
struct Base {
virtual ~Base() = default;
};
struct Derived : Base {};
Base *clone(Base *b) {
const auto &type = typeid(*b);
if (type == typeid(Base)) {
return clone_helper<Base>(b);
}
if (type == typeid(Derived)) {
return clone_helper<Derived>(b);
}
throw std::domain_error(std::string("No cloning provided for type ") + typeid(*b).name());
}
int main() {
Derived d;
Base *ptr = &d;
auto ptr2 = clone(ptr);
assert(typeid(*ptr2) == typeid(Derived));
}
This will find at runtime if you did not provide a clone method. It may be slower than usual. Sadly a switch is not possible since we cannot obtain the typeid of a type at compile time.
You may like to implement clone function in a separate class template, which is only applied to derived classes when an object of a derived class is created. The derived classes do not implement clone (keep it pure virtual) to avoid forgetting to override it in a further derived class.
Example:
struct Base {
virtual Base* clone() const = 0;
virtual ~Base() noexcept = default;
};
template<class Derived>
struct CloneImpl final : Derived {
using Derived::Derived;
CloneImpl* clone() const override { // Covariant return type.
return new CloneImpl(*this);
}
};
template<class T>
std::unique_ptr<T> clone(T const& t) { // unique_ptr to avoid leaks.
return std::unique_ptr<T>(t.clone());
}
struct Derived : Base {};
struct Derived2 : Derived {};
int main() {
CloneImpl<Derived> d1; // Apply CloneImpl to Derived when creating an object.
auto d2 = clone(d1);
auto d3 = clone(*d2);
CloneImpl<Derived2> c1; // Apply CloneImpl to Derived2 when creating an object.
auto c2 = clone(c1);
auto c3 = clone(*c2);
}
See https://stackoverflow.com/a/16648036/412080 for more details about implementing interface hierarchies without code duplication.
class Base {
virtual void func1();
}
class Derived : Base {
void func1();
void func2();
}
vector<Base *> vec;
vec.push_back(new Base()), vec.push_back(new Derived());
What is the correct/clean way to call func2 without knowing which index corresponds to which class? Is there a convention to do such a thing? I also want to avoid using typeid.
In your case the objects are sliced, as mentioned in king_nak's answer, so there's no safe way to call func2().
But you can store pointers to Base instead of Base objects - in this case you can use dynamic_cast:
std::vector<Base*> vec;
vec.push_back(new Base());
vec.push_back(new Derived());
for (auto obj : vec)
{
Derived* d = dynamic_cast<Derived*>(obj);
if (d)
{
d->func2();
}
}
Some info on dynamic_cast: link
PS: Also, if you want to call function func2() on Base objects, I think it makes sense to add a stupid implementation to Base class and make the function virtual.
This function will take one of said pointers and call func2 if possible, and simply return false otherwise
bool CallFunc2(Base* Bae){
Derived* Der;
if (Der = dynamic_cast<Derived*>(Bae))
{Der->func2(); return true;}
else
return false;
}
This works on the principle that dynamic_cast returns a null pointer if the object being cast cannot be converted.
If you don't want to use RTTI at all (including dynamic_cast), you could simulate its behaviour like Qt does it with qgraphicsitem_cast
Outline:
class Base {
public:
enum { Type = 0 };
virtual int type() { return Type; }
};
class Derived : public Base {
public:
enum { Type = 1 };
int type() { return Type; }
};
template<typename T>
inline T myobject_cast(Base *b) {
if (b) {
// Requires C++11
if (int(std::remove_pointer<T>::type::Type) == b->type()) {
return static_cast<T>(b);
}
/* Pre C++11 (might be UB, but works on many compilers, OpenSource and Commercial)
if (int(static_cast<T>(0)->Type) == b->type()) {
return static_cast<T>(b);
}
*/
}
return NULL;
}
// use:
Base *b = new Base;
Base *d = new Derived;
Derived *o1 = myobject_cast<Derived*> (b); // NULL
Derived *o2 = myobject_cast<Derived*> (d); // d
Each class would require a unique Type member for this to work.
Be aware that this will not work with "intermediate" classes in the hierarchy. Only the actual, most derived type will can be cast to (e.g. a DerivedDerived cannot be cast to a Derived, or Base for that matter).
You might also find an overload for const handy:
template<typename T> inline T myobject_cast(const Base *b)
{ return (b && int(static_cast<T>(0)->Type) == b->type()) ? static_cast<T>(p) : 0; }
const Base *cb = new Derived;
const Derived *co = myobject_cast<const Derived *>(cb);
I have a function that looks like:
// this function might modify base_ptr
void SomeFunction(shared_ptr<Base> &base_ptr)
{ if(some_condition) { base_ptr = some_other_ptr; } }
I'd like to call the function with a shared_ptr:
shared_ptr<Derived> d = ...;
SomeFunction(d);
This doesn't work though. It doesn't work if I'm using normal pointers either (ie. implicit casting to Base* & from Derived*. One workaround is to create a Base pointer from the Derived one, and then pass that to the function.
shared_ptr<Base> base = d;
SomeFunction(b);
But this isn't very pretty from a coding standpoint. It also adds confusion and the potential for a subtle bug:
shared_ptr<Derived> d = derived;
shared_ptr<Base> b = derived;
SomeFunction(b);
// b and d might now be pointing to different things -- not good!
Is there better way to do this?
What you are trying to do is inherently dangerous, and C++ is making it hard on purpose. Consider if C++ allowed you to call SomeFunction the way you wanted. Then you could do this:
struct Base {
};
struct Derived1 : Base {
void f1();
};
struct Derived2 : Base {
void f2();
};
void SomeFunction(shared_ptr<Base> &p)
{
p = make_shared<Derived2>(); // nothing wrong with converting
// a Derived2 pointer to a Base pointer.
}
int main()
{
shared_ptr<Derived1> d = make_shared<Derived1>();
SomeFunction(d); // An error, but what if it wasn't?
d->f1(); // Trying to call method f1 of a Derived2!
}
The compiler would not be able to know that d changed from a Derived1 pointer to a Derived2 pointer, so it wouldn't be able to give you a compile error when you tried to call method f1 of a Derived2.
You could template the function for the smart pointer's type
#include <iostream>
#include <memory>
#include <type_traits>
using namespace std;
class Base {
public:
virtual void hello() {
cout << "hello base" << endl;
}
};
class Derived : public Base {
public:
void hello() {
cout << "hello derived" << endl;
}
};
class otherClass {
public:
};
template<typename T>
void SomeFunction(shared_ptr<T> &base_ptr)
{
static_assert(is_base_of<Base, T>::value == true, "Wrong non-derived type");
base_ptr->hello();
// Rebase it
base_ptr.reset(new Derived);
base_ptr->hello();
}
int main() {
shared_ptr<Base> obj(new Base());
SomeFunction(obj);
// hello base
// hello derived
shared_ptr<Derived> obj2(new Derived());
// hello derived
// hello derived
SomeFunction(obj2);
shared_ptr<otherClass> obj3(new otherClass());
SomeFunction(obj3); // ASSERT
return 0;
}
http://ideone.com/ATqhEZ
If you intend to update all the smart pointers when you reset one, you'll have to do some book-keeping by yourself since they're not designed to have a "signal-like" mechanism to notify other smart pointers pointing to the same object.
Edited my answer to provide compile-time safety if you intend to use it with Base and relative subclasses.
Warning: the above solution uses C++11, the same could be accomplished in a similar way in pre-C++11 code
I am quite confused with the dynamic_cast keyword in C++.
struct A {
virtual void f() { }
};
struct B : public A { };
struct C { };
void f () {
A a;
B b;
A* ap = &b;
B* b1 = dynamic_cast<B*> (&a); // NULL, because 'a' is not a 'B'
B* b2 = dynamic_cast<B*> (ap); // 'b'
C* c = dynamic_cast<C*> (ap); // NULL.
A& ar = dynamic_cast<A&> (*ap); // Ok.
B& br = dynamic_cast<B&> (*ap); // Ok.
C& cr = dynamic_cast<C&> (*ap); // std::bad_cast
}
the definition says:
The dynamic_cast keyword casts a datum from one pointer or reference
type to another, performing a runtime check to ensure the validity of the cast
Can we write an equivalent of dynamic_cast of C++ in C so that I could better understand things?
Here's a rundown on static_cast<> and dynamic_cast<> specifically as they pertain to pointers. This is just a 101-level rundown, it does not cover all the intricacies.
static_cast< Type* >(ptr)
This takes the pointer in ptr and tries to safely cast it to a pointer of type Type*. This cast is done at compile time. It will only perform the cast if the types are related. If the types are not related, you will get a compiler error. For example:
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
dynamic_cast< Type* >(ptr)
This again tries to take the pointer in ptr and safely cast it to a pointer of type Type*. But this cast is executed at runtime, not compile time. Because this is a run-time cast, it is useful especially when combined with polymorphic classes. In fact, in certain cases the classes must be polymorphic in order for the cast to be legal.
Casts can go in one of two directions: from base to derived (B2D) or from derived to base (D2B). It's simple enough to see how D2B casts would work at runtime. Either ptr was derived from Type or it wasn't. In the case of D2B dynamic_cast<>s, the rules are simple. You can try to cast anything to anything else, and if ptr was in fact derived from Type, you'll get a Type* pointer back from dynamic_cast. Otherwise, you'll get a NULL pointer.
But B2D casts are a little more complicated. Consider the following code:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main() can't tell what kind of object CreateRandom() will return, so the C-style cast Bar* bar = (Bar*)base; is decidedly not type-safe. How could you fix this? One way would be to add a function like bool AreYouABar() const = 0; to the base class and return true from Bar and false from Foo. But there is another way: use dynamic_cast<>:
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
The casts execute at runtime, and work by querying the object (no need to worry about how for now), asking it if it the type we're looking for. If it is, dynamic_cast<Type*> returns a pointer; otherwise it returns NULL.
In order for this base-to-derived casting to work using dynamic_cast<>, Base, Foo and Bar must be what the Standard calls polymorphic types. In order to be a polymorphic type, your class must have at least one virtual function. If your classes are not polymorphic types, the base-to-derived use of dynamic_cast will not compile. Example:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
Adding a virtual function to base, such as a virtual dtor, will make both Base and Der polymorphic types:
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}
Unless you're implementing your own hand-rolled RTTI (and bypassing the system one), it's not possible to implement dynamic_cast directly in C++ user-level code. dynamic_cast is very much tied into the C++ implementation's RTTI system.
But, to help you understand RTTI (and thus dynamic_cast) more, you should read up on the <typeinfo> header, and the typeid operator. This returns the type info corresponding to the object you have at hand, and you can inquire various (limited) things from these type info objects.
More than code in C, I think that an english definition could be enough:
Given a class Base of which there is a derived class Derived, dynamic_cast will convert a Base pointer to a Derived pointer if and only if the actual object pointed at is in fact a Derived object.
class Base { virtual ~Base() {} };
class Derived : public Base {};
class Derived2 : public Base {};
class ReDerived : public Derived {};
void test( Base & base )
{
dynamic_cast<Derived&>(base);
}
int main() {
Base b;
Derived d;
Derived2 d2;
ReDerived rd;
test( b ); // throw: b is not a Derived object
test( d ); // ok
test( d2 ); // throw: d2 is not a Derived object
test( rd ); // ok: rd is a ReDerived, and thus a derived object
}
In the example, the call to test binds different objects to a reference to Base. Internally the reference is downcasted to a reference to Derived in a typesafe way: the downcast will succeed only for those cases where the referenced object is indeed an instance of Derived.
First, to describe dynamic cast in C terms, we have to represent classes in C.
Classes with virtual functions use a "VTABLE" of pointers to the virtual functions.
Comments are C++. Feel free to reformat and fix compile errors...
// class A { public: int data; virtual int GetData(){return data;} };
typedef struct A { void**vtable; int data;} A;
int AGetData(A*this){ return this->data; }
void * Avtable[] = { (void*)AGetData };
A * newA() { A*res = malloc(sizeof(A)); res->vtable = Avtable; return res; }
// class B : public class A { public: int moredata; virtual int GetData(){return data+1;} }
typedef struct B { void**vtable; int data; int moredata; } B;
int BGetData(B*this){ return this->data + 1; }
void * Bvtable[] = { (void*)BGetData };
B * newB() { B*res = malloc(sizeof(B)); res->vtable = Bvtable; return res; }
// int temp = ptr->GetData();
int temp = ((int(*)())ptr->vtable[0])();
Then a dynamic cast is something like:
// A * ptr = new B();
A * ptr = (A*) newB();
// B * aB = dynamic_cast<B>(ptr);
B * aB = ( ptr->vtable == Bvtable ? (B*) aB : (B*) 0 );
The following is not really close to what you get from C++'s dynamic_cast in terms of type checking but maybe it will help you understand its purpose a little bit better:
struct Animal // Would be a base class in C++
{
enum Type { Dog, Cat };
Type type;
};
Animal * make_dog()
{
Animal * dog = new Animal;
dog->type = Animal::Dog;
return dog;
}
Animal * make_cat()
{
Animal * cat = new Animal;
cat->type = Animal::Cat;
return cat;
}
Animal * dyn_cast(AnimalType type, Animal * animal)
{
if(animal->type == type)
return animal;
return 0;
}
void bark(Animal * dog)
{
assert(dog->type == Animal::Dog);
// make "dog" bark
}
int main()
{
Animal * animal;
if(rand() % 2)
animal = make_dog();
else
animal = make_cat();
// At this point we have no idea what kind of animal we have
// so we use dyn_cast to see if it's a dog
if(dyn_cast(Animal::Dog, animal))
{
bark(animal); // we are sure the call is safe
}
delete animal;
}
A dynamic_cast performs a type checking using RTTI. If it fails it'll throw you an exception (if you gave it a reference) or NULL if you gave it a pointer.
There are no classes in C, so it's impossible to to write dynamic_cast in that language. C structures don't have methods (as a result, they don't have virtual methods), so there is nothing "dynamic" in it.
No, not easily. The compiler assigns a unique identity to every class, that information is referenced by every object instance, and that is what gets inspected at runtime to determine if a dynamic cast is legal. You could create a standard base class with this information and operators to do the runtime inspection on that base class, then any derived class would inform the base class of its place in the class hierarchy and any instances of those classes would be runtime-castable via your operations.
edit
Here's an implementation that demonstrates one technique. I'm not claiming the compiler uses anything like this, but I think it demonstrates the concepts:
class SafeCastableBase
{
public:
typedef long TypeID;
static TypeID s_nextTypeID;
static TypeID GetNextTypeID()
{
return s_nextTypeID++;
}
static TypeID GetTypeID()
{
return 0;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return false; }
return true;
}
template <class Target>
static Target *SafeCast(SafeCastableBase *pSource)
{
if (pSource->CanCastTo(Target::GetTypeID()))
{
return (Target*)pSource;
}
return NULL;
}
};
SafeCastableBase::TypeID SafeCastableBase::s_nextTypeID = 1;
class TypeIDInitializer
{
public:
TypeIDInitializer(SafeCastableBase::TypeID *pTypeID)
{
*pTypeID = SafeCastableBase::GetNextTypeID();
}
};
class ChildCastable : public SafeCastableBase
{
public:
static TypeID s_typeID;
static TypeID GetTypeID()
{
return s_typeID;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); }
return true;
}
};
SafeCastableBase::TypeID ChildCastable::s_typeID;
TypeIDInitializer ChildCastableInitializer(&ChildCastable::s_typeID);
class PeerChildCastable : public SafeCastableBase
{
public:
static TypeID s_typeID;
static TypeID GetTypeID()
{
return s_typeID;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); }
return true;
}
};
SafeCastableBase::TypeID PeerChildCastable::s_typeID;
TypeIDInitializer PeerChildCastableInitializer(&PeerChildCastable::s_typeID);
int _tmain(int argc, _TCHAR* argv[])
{
ChildCastable *pChild = new ChildCastable();
SafeCastableBase *pBase = new SafeCastableBase();
PeerChildCastable *pPeerChild = new PeerChildCastable();
ChildCastable *pSameChild = SafeCastableBase::SafeCast<ChildCastable>(pChild);
SafeCastableBase *pBaseToChild = SafeCastableBase::SafeCast<SafeCastableBase>(pChild);
ChildCastable *pNullDownCast = SafeCastableBase::SafeCast<ChildCastable>(pBase);
SafeCastableBase *pBaseToPeerChild = SafeCastableBase::SafeCast<SafeCastableBase>(pPeerChild);
ChildCastable *pNullCrossCast = SafeCastableBase::SafeCast<ChildCastable>(pPeerChild);
return 0;
}
static_cast< Type* >(ptr)
static_cast in C++ can be used in scenarios where all type casting can be verified at compile time.
dynamic_cast< Type* >(ptr)
dynamic_cast in C++ can be used to perform type safe down casting. dynamic_cast is run time polymorphism. The dynamic_cast operator, which safely converts from a pointer (or reference) to a base type to a pointer (or reference) to a derived type.
eg 1:
#include <iostream>
using namespace std;
class A
{
public:
virtual void f(){cout << "A::f()" << endl;}
};
class B : public A
{
public:
void f(){cout << "B::f()" << endl;}
};
int main()
{
A a;
B b;
a.f(); // A::f()
b.f(); // B::f()
A *pA = &a;
B *pB = &b;
pA->f(); // A::f()
pB->f(); // B::f()
pA = &b;
// pB = &a; // not allowed
pB = dynamic_cast<B*>(&a); // allowed but it returns NULL
return 0;
}
For more information click here
eg 2:
#include <iostream>
using namespace std;
class A {
public:
virtual void print()const {cout << " A\n";}
};
class B {
public:
virtual void print()const {cout << " B\n";}
};
class C: public A, public B {
public:
void print()const {cout << " C\n";}
};
int main()
{
A* a = new A;
B* b = new B;
C* c = new C;
a -> print(); b -> print(); c -> print();
b = dynamic_cast< B*>(a); //fails
if (b)
b -> print();
else
cout << "no B\n";
a = c;
a -> print(); //C prints
b = dynamic_cast< B*>(a); //succeeds
if (b)
b -> print();
else
cout << "no B\n";
}
dynamic_cast uses RTTI. It can slow down your application, you can use modification of the visitor design pattern to achieve downcasting without RTTI http://arturx64.github.io/programming-world/2016/02/06/lazy-visitor.html