Introduction

As it is well known smart pointer with reference counting in C++ are responsible for sharing object pointer and managing its memory life cycle. When using smart pointers it is assumed that internal object pointer that is managed by the smart pointer is not accessible outside the smart pointer. Accessability of the internal object pointer outside the smart pointer may lead to an accidental pointer deletion and subsequent memory problems. In order to avoid such problems it would be great to allow object pointer creation only within the smart pointer and forbid its creation outside the smart pointer.

Background

In one of my projects we built a framework that introduced a bunch of base classes that the framework works with. The framework makes use of only smart pointers created from these base classes for controling the class objects memory life cycle. User may extend the framework by subclassing these base classes, however the framework utilizes only smart pointers created from these derived user classes. In order to avoid memory problems described above a request appeared to disallow derived classes construction on the heap (pointers) as well as on the stack (it is 'nice to have' ability) and allow only derived classes smart pointers costructruction. All this have to be done by means of the framework without any assistance from the user, in other words this should be enforced over the user derived classes.

Code overview

In the article I show the code that allows base class to prohibit its derived classes construction on the stack and on the heap from outside the base class and enforce all derived classes to be constructed from a single construction points within the base class.

Here is an example of the Base class that achieves the declared goal.

class Base
{
public:
    class ForbidConstruction
    {            
    private:
        ForbidConstruction()
        {}

        ForbidConstruction(const ForbidConstruction&);
        ForbidConstruction& operator=(const ForbidConstruction&);

        friend class Base;    
    };   
    
    Base(const ForbidConstruction& /* dummy parameter */)
    {
	// Do some construction activity
        	...
    } 
    
    virtual ~Base() {}

    template <typename T>
    static   SmartPtr<T> create() 
    { 
        return SmartPtr<T>( new T( Base::ForbidConstruction() ) ); 
    }

private:
    Base(const Base&);
    Base& operator=(const Base&);
};

class Derived: public Base
{
public:
    Derived(const Base::ForbidConstruction& dummy, /* other constructor parameters */) : 
	Base(dummy)
    {
	// Do some construction activity
	...
    }
    ...
};
 
int main()
{
    SmartPtr<Derived> derived = Base::create<Derived>();
}

The class Base has public constructor that accepts an internal class ForbidConstruction reference. Note that internal class ForbidConstruction has private constructor and thus can be created only within class Base that is declared as its friend. Any class that is derived from the Base class should pass ForbidConstruction object to the Base class constructor. However the derived class is not able to construct the ForbidConstruction object itself, so the only option is to accept ForbidConstruction object as the derived class constructor parameter.

Since ForbidConstruction object can not be created anywhere outside the Base class the Derived object can not be created neither on the stack nor on the heap (pointer) outside the Base class. So the only way to construct the Derived object is from within Base class. The Base class provides static templated create() method that creates the Derived object pointer and returns it wrapped within a smart pointer SmartPtr class.

With the above preparations made in the Base class only we are able to create robust framework that does not suffer from an accidental derived class pointer deletion.