Re: Зачем нужен невиртуальный деструктор?
От: rg45 СССР  
Дата: 09.12.10 09:55
Оценка: 1 (1) +1
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Реализовать гибкую стратегию владения объектами можно и без виртуальных деструкторов. Приведу пример. Я определяю некий абстракный интерфейс, состоящий полностью из чисто виртуальных функций:
class IFoo
{
public:

  virtual void bar() = 0;
  virtual void baz() = 0;

protected:
  IFoo() { }
};

Причем деструктор этого абстрактного класса я намеренно объявляю невиртуальным и защищенным, тем самым как бы подчеркивая, что стратегия владения объектами выбирается разработчиком производных классов. При этом у разработчика производного класса есть две возможности: 1) (традиционный) сделать деструктор производного класса открытым и виртуальным; 2) сделать деструктор невиртуальным и защищенным, а для создания объектов реализовать фабричный метод.

Пример второго варианта:
using boost::shared_ptr;

class FooDerived1 : public IFoo
{
public:

  virtual void bar();
  virtual void baz();

  static shared_ptr<FooDerived1> create_instance(/*possible arguments*/);
  {
    return shared_ptr<FooDerived1>(new FooDerived(/*possible arguments*/));
  }

protected:
  FooDerived1();
};

class FooDerived2 : public IFoo { /*...*/ };
class FooDerived3 : public IFoo { /*...*/ };

А вот теперь замечательный момент: умный указатель производного типа, возвращаемый фабричным методом create_instance, легко преобразуется в умный указатель абстрактного типа. Это позволяет владеть объектами и корректно удалять их полиморфно:
int main()
{
  typedef std::vector<boost::shared_ptr<IFoo> > Items;

  Items items;
  items.push_back(FooDerived1::create_instance(/*possible arguments*/));
  items.push_back(FooDerived2::create_instance(/*possible arguments*/));
  items.push_back(FooDerived3::create_instance(/*possible arguments*/));

  //...
}

Преимущество такого подхода: отделение основной функциональности абстрактных классов от способов владения конкретными объектами. Т.о. в прикладной программе точка создания объектов как бы изолирована от использования этих объектов. Это улучшает структурированность кода, тестируемость и пр. и др.
--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.