#c #oop #stl
#c #ооп #stl
Вопрос:
Мои знания ООП немного подзабыты… и я, кажется, первый раз пробую полиморфизм с контейнерами.
class car {
public: std::string color;
public: virtual void foo (void) = 0;
public: virtual ~car (void){}
};
class truck : public car {
public: int tonnage;
public: virtual void foo (void) {}
};
// expect for subclasses of car
…
truck *t = new truck ();
t->color="white";
t->tonnage=32;
std::list <car *> lst; // for any kind of car
lst.push_back (t);
printf ("n1: %s", typeid (t).name ());
printf ("n2: %s", typeid (lst.front()).name());
Я ожидал увидеть
1: P3van
2: P3van
но это было
1: P3van
2: P3car
Это невозможно с контейнерами или в чем проблема?
Мне нужно создать подкласс из него, а не родительский. Насколько я читал, нарезка не является проблемой с указателями.
Спасибо за помощь!
ПРАВКА1:
Я добавил виртуальные функции. Но это тот же результат.
ПРАВКА2:
Я хотел бы понизить значение с помощью typid-info. В противном случае я мог бы поместить идентификатор-элемент в базовый класс, но я думал, что это будет возможно (например, динамическая проверка типов / приведение).
Комментарии:
1. Для того, чтобы полиморфизм действительно работал, базовый класс должен содержать по крайней мере одну
virtual
функцию (которая в полиморфном контексте должна быть по крайней мереvirtual
деструктором).2. Ваши классы не являются полиморфными. Они используют простое отношение наследования «is a». Чтобы набор классов был полиморфным, они должны иметь виртуальные функции-члены.
3. И результат правильный. Содержимое списков является указателем на
car
. Эти указатели могут быть преобразованы в указатели наtruck
, хотя, если они действительно являются указателями наtruck
экземпляры.4. Вы действительно думаете, что это имеет отношение к контейнерам «STL»? Вы пробовали обходиться без него?
5. typeid(*(lst.front()))
Ответ №1:
C определяет полиморфный класс как класс, который имеет по крайней мере одну виртуальную функцию. typeid
не делает ничего особенного, если его аргументом не является полиморфный класс. Итак, сначала добавьте виртуальный деструктор в car
:
class car {
public:
virtual ~car() {}
std::string color;
};
Кроме того, typeid
не действует полиморфно на указатели, только на объекты / ссылки. Попробуйте
printf ("n1: %s", typeid (*t).name ());
printf ("n2: %s", typeid (*lst.front()).name());
Ответ №2:
typeid() не является функцией-членом класса car . Таким образом, полиморфизм здесь неприменим. Вместо typeid(XXX).name() вызовите XXX->some_virtual_member_function(), и вы увидите то, на что надеялись.
В качестве альтернативы, если это не тип указателя, который вы искали, а тип объекта, вам следует вызывать typeid для объектов, а не указателей.
Например. вместо typeid(t) вызовите typeid(*t).
Комментарии:
1. typeid if для динамической проверки типов и, таким образом, часть c