al leer "Más allá de la biblioteca C++ estándar: Una introducción a la Boost", tengo un ejemplo muy interesante:cómo funciona boost :: ~ shared_ptr?
class A
{
public:
virtual void sing()=0;
protected:
virtual ~A() {};
};
class B : public A
{
public:
virtual void sing()
{
std::cout << "Do re mi fa so la"<<std::endl;;
}
};
y hacer algunas pruebas:
int main()
{
//1
std::auto_ptr<A> a(new B); //will not compile ,error: ‘virtual A::~A()’ is protected
//2
A *pa = new B;
delete pa; //will not compile ,error: ‘virtual A::~A()’ is protected
delete (dynamic_cast<B*>(pa)); //ok
//3
boost::shared_ptr<A> a(new B);//ok
}
lo que soy muy curioso aquí ¿Cómo funciona ~ shared_ptr? cómo se deduce la clase derivada B?
Gracias por su ayuda!
gracias a todos, escribo una simple muestra de cómo ~ shared_ptr funciona
class sp_counted_base
{
public:
virtual ~sp_counted_base(){}
};
template<typename T>
class sp_counted_base_impl : public sp_counted_base
{
public:
sp_counted_base_impl(T *t):t_(t){}
~sp_counted_base_impl(){delete t_;}
private:
T *t_;
};
class shared_count
{
public:
static int count_;
template<typename T>
shared_count(T *t):
t_(new sp_counted_base_impl<T>(t))
{
count_ ++;
}
void release()
{
--count_;
if(0 == count_) delete t_;
}
~shared_count()
{
release();
}
private:
sp_counted_base *t_;
};
int shared_count::count_(0);
template<typename T>
class myautoptr
{
public:
template<typename Y>
myautoptr(Y* y):sc_(y),t_(y){}
~myautoptr(){ sc_.release();}
private:
shared_count sc_;
T *t_;
};
int main()
{
myautoptr<A> a(new B);
}
la clave es:
- función de plantilla constructo
- el recurso no elimina en ~ shared_ptr, se es eliminado por shared_count
Técnicamente hablando, REALIZA una conversión de B * a A *. Todos los accesos posteriores al puntero usarán el tipo A *. Las operaciones en tipo B son a través de polimorfismo estándar (pasan por A *). La única excepción es el destructor, que shared_ptr recuerda a través de su mecanismo "deleter" (o alguna generalización del mismo). – nobar