Здравствуйте, 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;
//...