Re[3]: Зачем нужен невиртуальный деструктор?
От: rg45 СССР  
Дата: 14.02.11 04:40
Оценка: 1 (1)
Здравствуйте, bzzz, Вы писали:

R>>...


B>Всё классно но ваш пример не работает, не могли бы вы написать работающий пример?


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

А вот работающий пример.

//IFoo.hpp
class IFoo
{
public:

  virtual void bar() = 0;

protected:
  IFoo() { }
};

//*.cpp
//#include "IFoo.hpp"
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <vector>

using boost::shared_ptr;

#define PRINT_FUNCTION_NAME() { std::cout << __FUNCTION__ << std::endl; }

class FooDerived1 : public IFoo
{
public:

  virtual void bar() { PRINT_FUNCTION_NAME(); }
  
  static shared_ptr<FooDerived1> create_instance()
  {
    return shared_ptr<FooDerived1>(new FooDerived1(), destroy);
  }

protected:
  ~FooDerived1() { PRINT_FUNCTION_NAME(); }
  static void destroy(FooDerived1* inst) { delete inst; }
};

class FooDerived2 : public IFoo 
{ 
public:

  virtual void bar() { PRINT_FUNCTION_NAME(); }

  virtual ~FooDerived2() { PRINT_FUNCTION_NAME(); }
};

void use(const std::vector<shared_ptr<IFoo> >& items)
{
  typedef std::vector<shared_ptr<IFoo> > Items;
  for(Items::const_iterator item = items.begin(); item != items.end(); ++item)
    (*item)->bar();
}

void do_nothing(void*) { }

int main()
{
  typedef std::vector<boost::shared_ptr<IFoo> > Items;

  Items items;
  
  FooDerived2 local;
  items.push_back(shared_ptr<FooDerived2>(&local, do_nothing));
  items.push_back(FooDerived1::create_instance());
  items.push_back(shared_ptr<FooDerived2>(new FooDerived2()));

  use(items);
}


Output:

FooDerived2::bar
FooDerived1::bar
FooDerived2::bar
FooDerived2::~FooDerived2
FooDerived1::~FooDerived1
FooDerived2::~FooDerived2


Собрано на msvc-9.0 (MSVS 2008), boost 1.45.0.

А теперь немного повторюсь. Ценность этого подхода в том, мухи отделены от котлет. Те части программы, которые используют полиморфные объекты, не интересуются ни способом их создания, ни областью памяти, в которой хранятся эти объекты, ни временем их жизни. Так, в этом примере два объекта расположены в динамической памяти, а один — во временной памяти функции main. Но внутри функции use, использующей эти объекты, все эти детали не интересны. А защищенный деструктор в абстрактном базовом классе дает нам защищенность от очумелых ручек, способных написать что угодно, в т.ч. и такое:

shared_ptr<IFoo> shared = ...;
IFoo* ptr = shared.get();
//...
delete ptr;
//...
--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.