Search code examples
c++boostdestructorshared-ptrprotected

How to use shared_ptr on a 3'd party class with protected destructor and public destroy method


I am a client of a class A which it's destructor is defined in protected. In addition I cannot change it's interface (I deliberately wrote "3'd party class", although I meant that for any reason, you aren't allowed to change its interface. So, How can I use boost::shared_ptr in such case? The destructor is virtual:

Class Foo {
    public:
        void Destroy () {}
    protected:
    virtual ~Foo () {}
}

For Foo, it provide a "Destroy" method

A Straight forward usage The following code won't compile:

  boost::shared_ptr <Foo> a = boost::make_shared <Foo> ();

Compiler message: ... error ..."Foo::~Foo() is inaccessible ...

Also, my workplace's compiler does not support c++11


Solution

  • You can create an intermediate class as a helper polymorphic base:

    Sample using only c++03 Live On Coliru:

    #include <boost/shared_ptr.hpp>
    #include <iostream>
    
    class Foo { // "abstract"
        public:
            virtual void Destroy () { std::cout << __FUNCTION__ << "\n"; }
        protected:
            virtual ~Foo () {}
    };
    
    class FooBase : public Foo {
        public:
            static void Deleter(FooBase* p) {
                if (p)
                    p->Destroy();
                delete p;
            }
    
        // protected:
            virtual ~FooBase() { std::cout << __FUNCTION__ << "\n"; }
    };
    
    class FooDerived : public FooBase
    {
        ~FooDerived() { std::cout << __FUNCTION__ << "\n"; }
    };
    
    int main()
    {
        boost::shared_ptr<FooBase> p(new FooDerived, FooBase::Deleter);
    }
    

    Prints:

    Destroy
    ~FooDerived
    ~FooBase
    

    Note How the destructor could actually be protected now. That ensures that all destructions go through FooBase::Deleter