Существует некоторое фундаментальное недопонимание относительно static_cast
: он просто делает приведение, и ваша ответственность за обеспечение того, чтобы приведенный указатель действительно указывал на объект целевого типа. , static_cast
будет возвращать нулевой указатель только в том случае, если указатель источника уже был сам по себе, но никогда при несоответствии типов!
class B { /*...*/ };
class D1 : public B { };
class D2 : public B { };
D1 d1;
B* b = &d1;
D2* d2 = static_cast<D2*>(b);
d2
будет указателем на d1 (в некоторых случаях, включающих множественное наследование, может быть смещение), но интерпретируйте данные последнего совершенно по-разному (если D1
и D2
не совместимы с компоновкой), и вы можете закончить в аду!
Теперь, во-первых, я лично предпочитаю модифицированную подпись:
template <typename CompType>
inline CompType* getComponent();
// ^
Позволяет вызывать вашу функцию как getComponent<SomeType>()
вместо getComponent<SomeType*>()
, кроме того, она позволяет использовать указатели внутри тела функции, что является более понятным, см. Мой соответствующий код, приведенный ниже.
Тогда то, что вам на самом деле нужно, это dynamic_cast
(немного подгоняя ваш код под мои личные предпочтения ...):
CompType* result = nullptr; // pointer: see above!
for(Component * currComp : compStruct.components)
{
result = dynamic_cast<CompType*>(currComp);
if(result)
break;
}
return result;
Редактировать: Догоняя Ншант Сингх Комментарий:
dynamic_cast
на самом деле довольно дорого.
Альтернативой может быть unordered_map
, заменяющий ваш вектор (пример настройки можно найти в type_index
документация ; конечно, вы бы поместили ваши объекты вместо строк .. .). Тогда ваш поиск может выглядеть так:
auto i = map.find(std::type_index(typeid(CompType));
return i == map.end() ? nullptr : static_cast<CompType*>(i->second);
// now, you CAN use static cast, as the map lookup provided you the
// necessary guarantee that the type of the pointee is correct!