STL:: контейнер, полиморфизм

#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