Предположим, мы имеем следующий код:Является ли такой снижающий сейф?
#include <memory>
#include <vector>
struct BaseComponent
{
template <typename T>
T * as()
{
return static_cast<T*>(this);
}
virtual ~BaseComponent() {}
};
template <typename T>
struct Component : public BaseComponent
{
virtual ~Component() {}
};
struct PositionComponent : public Component<PositionComponent>
{
float x, y, z;
virtual ~PositionComponent() {}
};
int main()
{
std::vector<std::unique_ptr<BaseComponent>> mComponents;
mComponents.emplace_back(new PositionComponent);
auto *pos = mComponents[0]->as<PositionComponent>();
pos->x = 1337;
return 0;
}
В Т * в качестве метода(), должен ли я использовать static_cast или dynamic_cast? есть времена, когда конверсия не сработает? Нужно ли мне вместо этого использовать dynamic_cast?
auto *ptr = dynamic_cast<T*>(this);
if(ptr == nullptr)
throw std::runtime_error("D'oh!");
return ptr;
Это обычно называется ** down ** cast, а не upcast. –
Каково использование аргумента шаблона T класса Component? – Jiwan
@ Reinhard: Я думаю, вы рисуете свои иерархии, отличные от меня (и большинство других людей), потому что для меня основы вверх, а производные типы вниз ... Обратите внимание, что * естественная * вещь на языке * будет понято *. Некоторые культуры указывают на будущее, некоторые указывают на прошлое, и в каждой культуре, указывающей в неправильном направлении, возникает путаница. Когда вы работаете с OO, консенсус в том, что вверх идет к базе, вниз к производным типам –