extending shared_ptr by inheritance

Since you will never manually delete it (and you should never manually delete anything, which is rather the point of shared_ptr in the first place), virtual destructors aren't really an issue.

Some interoperability problems may come up, though.

  1. You only get your derived class when you create specific instances of it. When you get a shared_ptr from somewhere like get_shared_from_this, it won't include your info.

  2. Function templates overloaded on shared_ptr<T> won't see the inheritance. Your derived class will suddenly appear foreign to random functions such as std::static_pointer_cast.

Fortunately, the C++ standard library is full of neat extensibility hooks. You can install a custom deleter like so:

template< typename t >
struct my_deleter
    : std::default_delete< t > {
    std::string info;

    my_deleter( std::string in_info )
        : info( std::move( in_info ) ) {}
};

std::shared_pointer< foo > myfoo( new foo, my_deleter{ "it's a foo" } );

and retrieve the info with a non-member function:

template< typename t >
std::string get_my_info( std::shared_ptr< t > ptr ) {
    my_deleter< t > * dp = std::get_deleter< my_deleter< t > >( ptr );
    if ( ! dp ) return {};
    return dp->info;
}

This isn't a very good program architecture, since there's only one custom deleter slot per shared object. It can do in a pinch, though.


In principle it is allowed to derive from STL classes, see here and here. However, you have to be aware that you should not work with a pointer to the base class -- i.e. a std::shared_ptr<myotherclass>* in this case.

So this and variants thereof should be forbidden:

std::shared_ptr<myotherclass>* ptr = new myclass(/* ... */);

... but agreed, that looks a bit synthetic.

Why is it forbidden? Because the STL classes do not have a virtual destructor. So when you want to delete your allocated class, the derived part remains. This in turn invokes undefined behaviour and possibly creates a memory leak -- even if you do not have some allocations in your derived class.

In order to do so, one possibility is to derive privately from shared_ptr:

class myclass : private std::shared_ptr<myotherclass> {};
                ^^^^^^^

This however might bring in problems with the binary compatibility, see the comments to this answer.

On the hand, even though the former is allowed, you can go on less error-prone and either use composition, where you make the shared_ptr a member of myclass and expose the required functionality (with the drawback that you sometimes have to expose a lot). Or you can set up a standalone function which does what you want ... I know you knew that ;-)