Home > Mobile >  Is there a fast (and unsafe) way to downcast pointers without checking?
Is there a fast (and unsafe) way to downcast pointers without checking?

Time:12-23

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.

  • Related