Приведение типа указателя наследника
#include<vector>
using namespace std;
class Hero {
protected:
int b;
public:
virtual void logic(int a) {
b = a;
cout << "hero" << ++a;
}
};
class Bad :public Hero
{
public:
void logic(int a, int b) {
this->b = a;
this->b = b;
cout << "bad"<<a<<b;
}
};
class Storage
{
vector<Hero*> heroes;
public:
template<class T>
void add_hero() {
heroes.push_back(new T());
}
template<class T>
T get() {
for (auto hero : heroes) {
if(typeid(hero)==typeid(T))
return hero;//вот проблемная строка
}
}
};
int main() {
Storage st;
st.add_hero<Hero>();
st.add_hero<Bad>();
st.get<Bad>().logic(10,2);
return 0;
}
как исправить
Ответы (2 шт):
Storage хранит вектор указателей на героев. После вызовов :
st.add_hero<Hero>();
st.add_hero<Bad>();
этот вектор будет хранить один адрес героя и один адрес плохого.
Теперь что делает st.get<Bad>()?
Она ничего не возвращает, так как вектор хранит Hero* и его тип не совпадает с типом Bad, а компилятор пытается как нибудь преобразовать Hero* в Bad. Если бы у него это получилось, то он мог вызвать функцию_член logic(10,2), но это не возможно. Вообще пишите что нибудь осмысленное. А то у вас ерунда какая то...
В цикле
for (auto hero : heroes) {
if(typeid(hero)==typeid(T))
return hero;//вот проблемная строка
}
переменная hero имеет тип указателя, а функция typeid в основном имеет смысл только для ссылок. Добавьте везде звёздочку.
for (auto hero : heroes) {
if(typeid(*hero)==typeid(T))
return *hero;//вот проблемная строка
}
дальше так как вы определили тип с помощью typeid, то вам нужно вручную сделать смену типа с помощью static_cast:
if(typeid(*hero)==typeid(T))
return static_cast<T&>(*hero);
Возвращать копию элемента всегда плохая идея, возвращайте ссылку.
template<class T>
T & get() {
for (auto hero : heroes) {
if(typeid(*hero)==typeid(T))
return static_cast<T&>(*hero);
}
}
