C++ Make derived class instantiable only from factory / base class

Viewed 59

I'm modelling classes to represent modules with sub-modules and so on. I make each sub-module to derive from the base class (Module).

But now I want to make it impossible to create sub-module from anywhere else than some specific method (like Factory pattern) - in order to provide some configuration for the sub-modules. See the code:

class Module
{
    public:
        template<typename T, typename... Args>
        std::shared_ptr<T> addSubModule(Args&&... args)
        {
            std::shared_ptr<T> module = std::make_shared<T>(args...);

            children.emplace_back(module);
            module->parent = this;

            return module;
        }

    protected:
        Module* parent = this;
        std::vector<std::shared_ptr<Module>> children;
};


class SomeSubModule : public Module
{
    public:
        SomeSubModule(int param1, int param2)
        {
            // ... some init
        }
};


void Usage()
{
    Module rootModule;

    rootModule.addSubModule<SomeSubModule>(1, 2);   // <-- Way 1) This is what I want
    SomeSubModule sub(1, 2);                        // <-- Way 2) This also works, but I want to prevent it
}

I want to make the "Way 1" the only way (so I can perform some init stuff in addSubModule, like add newly created module to a vector of children, init the parent pointer, etc).
The way I wrote it, the "Way 2" is still possible and I don't want it.

1 Answers

Generally, when we want to control the construction of a class (say, it only ever gets heap allocated with smart pointers, never declared as a local value) you do that by not making the constructors public!

The constructor should be non-public and only accessible by the other code that is supposed to use it. The simple way is to use friend. In Boost you can find more complex ways like declaring another type that serves as an access pathway, and that's handy for wrangling large numbers of submodules.

Related