I want to downcast a base class pointer to a derived class pointer.
I know that dynamic cast is costly so I want to avoid it. In my case, I am fully aware of the actual class the pointer in question points to. Is there a faster way to downcast it than dynamic casting?
I tried to use static_cast
but it won't apply here, because there is virtual inheritance in my class hierarchy.
CodePudding user response:
It does seem that this is exactly what virtual methods are for. Appropriate use of virtual methods eliminates most needs of dynamic casting. And it even works with virtual inheritance.
#include <stdexcept>
#include <iostream>
class Derived;
class Base {
public:
virtual Derived *to_derived()
{
throw std::runtime_error("Nope");
}
};
class Derived : virtual public Base {
public:
Derived *to_derived() override
{
return this;
}
};
class DerivedAgain : public Derived
{
};
int main()
{
DerivedAgain kit_and_kaboodle;
Base *p=&kit_and_kaboodle;
std::cout << (p->to_derived() ? "it works\n":"no it doesn't\n");
return 0;
}
Add a const
overload, for const-correctness, if needed.
CodePudding user response:
reinterpret_cast<>
is the answer to the basic question of what will downcast without any dynamic checks. It's the strongest (i.e. least-safe) cast this side of a C-style cast.
CodePudding user response:
This is not advised but, if you are absolutely certain you have a pointer to a child class that has been assigned to be a pointer to a base class then you can "downcast" it since it is, in reality, already a pointer to that child class. This is best done by a nested static_cast
. In the example code it's static_cast<B*>(static_cast<void*>(pa));
#include <iostream>
class A {
public:
virtual int ret() {return 1;}
};
class B : public A {
public:
virtual int ret() override { return 2; };
};
int main()
{
B b;
A *pa = &b;
B *pb = static_cast<B*>(static_cast<void*>(pa));
std::cout << pb->ret() << '\n';
pa = pb; // of course the pointer can be reassigned to the base class
}
This is not UB if, and only if, the pointer you downcast points to the child class.