Умные указатели (shared_ptr)
foo - указатель на объект родителя A
auto bar = std::static_pointer_cast<B>(foo); - присваивание указателю дочернего класса указатель на родительский объект(???)
Как это работает? Если только указатель родительского класса может содержать ссылки на дочерние объекты, но не наоборот
#include <iostream>
#include <memory>
struct A {
static const char* static_type;
const char* dynamic_type;
A() { dynamic_type = static_type; }
};
struct B : A {
static const char* static_type;
B() { dynamic_type = static_type; }
};
const char* A::static_type = "class A";
const char* B::static_type = "class B";
int main() {
std::shared_ptr<A> foo;
std::shared_ptr<B> bar;
foo = std::make_shared<A>();
bar = std::static_pointer_cast<B>(foo);
std::cout << "foo's static type: " << foo->static_type << '\n';
std::cout << "foo's dynamic type: " << foo->dynamic_type << '\n';
std::cout << "bar's static type: " << bar->static_type << '\n';
std::cout << "bar's dynamic type: " << bar->dynamic_type << '\n';
return 0;
}
Output:
foo's static type: class A
foo's dynamic type: class A
bar's static type: class B
bar's dynamic type: class A
Ответы (1 шт):
std::static_pointer_cast - это на самом деле обычный static_cast. Просто для умных указателей. Если посмотреть в возможные реализации на cppreference, то это стает очевидно.
Собственно, проблема сводится к более простой.
A* a = new A;
B* b = static_cast<B*>(b);
А все потому что это такой каст. Он просто проверяет что два класса находятся в правильной иерархии наследования. И делает он это на этапе компиляции. А в этот момент настоящие типы не известны (на самом деле компилятор мог бы и догадаться, и ошибку компиляции показать, но...) dynamic_cast/dynamic_pointer_cast все бы нашел и возвратил бы nullptr.
p.s. в Вашем примере есть небольшая ошибка - он не компилируется. переменная foo объявлена дважды.