как работает boost :: ~ shared_ptr? - PullRequest
       5

как работает boost :: ~ shared_ptr?

13 голосов
/ 30 декабря 2010

читая «За пределами стандартной библиотеки C ++: введение в Boost», я получил очень интересный пример:

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;;  
    }  
};  

и я провожу тестирование:

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

}

Что мне очень интересно, вот как работает ~ shared_ptr? как это вывести производный класс B?

Спасибо заранее за вашу помощь!

спасибо всем, Я пишу простой пример о том, как ~ shared_ptr работает

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);
}

ключ:

  1. функция построения шаблона
  2. ресурс не удален в ~ shared_ptr, он удален с помощью shared_count

Ответы [ 2 ]

11 голосов
/ 30 декабря 2010

Удивительно, но ключ здесь не в boost::shared_ptr деструкторе, а в его конструкторе (ах).

Если вы посмотрите на boost/shared_ptr.hpp, вы увидите, что shared_ptr<T> не просто имеет конструктор, ожидающий T *, но:

template<class Y>
explicit shared_ptr( Y * p );

В //3, когда вы строите boost::shared_ptr из B *, преобразование в A * не выполняется, а внутренние элементы shared_ptr создаются с фактическим типом B. После уничтожения объекта удаление происходит по указателю B (а не через указатель базового класса).

3 голосов
/ 30 декабря 2010

Шаблон класса shared_ptr имеет член типа класса shared_count, который, в свою очередь, имеет член типа указатель на класс sp_counted_base.Шаблон конструктора для класса shared_count назначает указатель на экземпляр шаблона класса sp_counted_impl_p этому члену, который определяется типом аргумента конструктора, а не shared_ptr::value_type.sp_counted_base имеет чисто виртуальную функцию-член dispose, которая перезаписывается на sp_counted_impl_p.Поскольку sp_counted_impl_p знает тип B в вашем примере, он может удалить его без доступа к деструктору базового класса, и поскольку он использует виртуальную диспетчеризацию, тип определяется во время выполнения.Этот метод требует сочетания параметрического и подтипного полиморфизма.

...