7
votes

I can understand why dynamic_cast does work in this case :

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
    virtual ~B() = default;
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << "a is a B" << std::endl;
}

int main() {
    f(C{});

    return 0;
}

But why if you remove the polymorphism from B it still works :

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << "a is a B" << std::endl;
}

int main() {
    f(C{});

    return 0;
}

Is it because dynamic_cast must only know the real type of the object you give has a parameter (as dynamic_cast<void*> / typeid would do), and after it knows the real type, it knows if the type is derived from a non polymorphic base?

1
Think vtable then think vptr. Which vtable do you need? Which object needs a vptr?curiousguy

1 Answers

8
votes

According to the Standard ([expr.dynamic.cast]p6) it is the object you cast should have a polymorphic type, not the one you trying to cast to.

And it is absolutely logical if you think about it. dynamic_cast requires some info to make casting (RTTI) and this info is tied to polymorphic types. So it doesn't matter if the parents of the type are polymorphic or not, the info about this class is right here. You do not need to know other's class RTTI to cast this object to it. You just need to know if this object is actually in some relationship with what you want to convert it to.