C ++ полиморфизм и нарезка - PullRequest
3 голосов
/ 04 апреля 2010

Следующий код, распечатывает

Derived
Base
Base

Но мне нужно, чтобы каждый производный объект помещался в User :: items, вызывал свою собственную функцию печати, но не базовый класс. Могу ли я достичь этого без использования указателей? Если это невозможно, как мне написать функцию, которая удаляет User :: items один за другим и освобождает память, чтобы не было утечек памяти?

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Base{
public:
  virtual void print(){ cout << "Base" << endl;}
};

class Derived: public Base{
public:
  void print(){ cout << "Derived" << endl;}
};

class User{
public:
  vector<Base> items;
  void add_item( Base& item ){
    item.print();
    items.push_back( item );
    items.back().print();
  }
};

void fill_items( User& u ){
  Derived d;
  u.add_item( d );
}

int main(){
  User u;
  fill_items( u );
  u.items[0].print();
}

Ответы [ 3 ]

5 голосов
/ 04 апреля 2010

Вам нужно использовать указатели, и вам нужно дать вашему базовому классу виртуальный деструктор. Деструктор не должен ничего делать, но он должен существовать. Ваша функция добавления выглядит следующим образом:

void add_item( Base * item ){
    item->print();
    items.push_back( item );
}

, где элементы vector<Base *>. Чтобы уничтожить предметы (в предположении виртуального деструктора):

for( int i = 0; i < items.size(); i++ ) {
    delete items[i];
}
items.clear();
1 голос
/ 04 апреля 2010

Вам необходим виртуальный деструктор для базы, чтобы убедиться, что объекты типа Derived правильно уничтожаются при вызове delete для указателя типа Base.

class Base{
public:
  virtual void print(){ cout << "Base" << endl;}

  virtual ~Base( ) { }  // virtual destructor
};

Затем вы можете использовать Boosts ptr_vector для хранения указателей на ваши объекты, которые удаляются при разрушении контейнера.

0 голосов
/ 08 апреля 2010

просто объясняю:

Чтобы понять, что происходит, вы можете попытаться определить класс Base abstract (например, определить любой метод, чисто виртуальный). В этом случае я ожидаю, что вы увидите ошибки компилятора. Таким образом, вы узнаете, что на самом деле делает вектор: он создает новые экземпляры класса Base с помощью конструкции копирования, когда вы нажимаете кнопку (производная). Вот почему вы хотите использовать указатели вместо этого. Тогда вектор работает с вашими изначально созданными объектами типа Derived вместо собственных копий типа Base.

...