Dynamic_cast на не полиморфных типах
Я могу понять, почему dynamic_cast работает в этом случае:
#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;
}
Но почему, если вы удалите полиморфизм из B, он все еще работает:
#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;
}
Это потому, что dynamic_cast должен знать только реальный тип объекта, который вы даете, имеет параметр (как dynamic_cast<void*>
/ typeid сделал бы), и после того, как он знает реальный тип, он знает, является ли тип производным от неполиморфного основания?
1 ответ
Согласно Стандарту ( [expr.dynamic.cast] p6), этот объект должен иметь полиморфный тип, а не тот, к которому вы пытаетесь привести.
И это абсолютно логично, если вы думаете об этом. dynamic_cast
требуется некоторая информация для приведения (RTTI), и эта информация связана с полиморфными типами. Так что не имеет значения, являются ли родители типа полиморфными или нет, информация об этом классе прямо здесь. Вам не нужно знать класс RTTI другого, чтобы привести этот объект к нему. Вам просто нужно знать, действительно ли этот объект связан с тем, во что вы хотите его преобразовать.