What are practical uses of a protected constructor?

C++ConstructorProtected

C++ Problem Overview


Why would anyone declare a constructor protected? I know that constructors are declared private for the purpose of not allowing their creation on stack.

C++ Solutions


Solution 1 - C++

When a class is (intended as) an abstract class, a protected constructor is exactly right. In that situation you don't want objects to be instantiated from the class but only use it to inherit from.

There are other uses cases, like when a certain set of construction parameters should be limited to derived classes.

Solution 2 - C++

Non-public constructors are useful when there are construction requirements that cannot be guaranteed solely by the constructor. For instance, if an initialization method needs to be called right after the constructor, or if the object needs to register itself with some container/manager object, this must be done outside the constructor. By limiting access to the constructor and providing only a factory method, you can ensure that any instance a user receives will fulfill all of its guarantees. This is also commonly used to implement a Singleton, which is really just another guarantee the class makes (that there will only be a single instance).

The reason for making the constructor protected, rather than private, is the same as for making any other method or field protected instead of private: so that it can be inherited by children. Perhaps you want a public, non-virtual factory method in the base class, which returns references to instances of the derived classes; the derived classes obviously want access to the parent constructors, but you still don't want to be creating them outside of your factory.

Solution 3 - C++

A protected constructor can be used to make a class effectively abstract when none of its methods are pure-virtual.

It is not quite abstract in the C++ sense since friend classes can still use it without overriding, but then you would have to declare these.

Solution 4 - C++

A protected constructor means that only derived members can construct instances of the class (and derived instances) using that constructor. This sounds a bit chicken-and-egg, but is sometimes useful when implementing class factories.

Solution 5 - C++

one use could be factory patterns

Solution 6 - C++

For factory methods with side-effects.

class mine {

  private:
    mine () {};

  protected:
    mine(int id) : m_id(id) {};

   int m_id;
   static int m_count;

  public:
    static mine* CreateOneOfMe() {
         return mine(m_count++);
    }

    int GetId() { return m_id; }

 };

This creates instances of the class and guarantees that each of them has a unique incrementing integer id. Note that if the constructor you want to use is not the default, you must hide the default too.

Solution 7 - C++

To let a subclass use a constructor that should not be accessible to an instantiator directly.

Solution 8 - C++

You could use it to limit the classes that could create it, for example:

class Level
{
private:

 Level();
 ~Level();

 friend class LevelManager;
};

The only class that can create an instance of it is the LevelManager class, so you will always know that the Level instance is created in the LevelManager.

Solution 9 - C++

One use of protected constructor is to implement the CRTP pattern, see the code below:

#include <iostream>
#include <assert.h>

template <class T>
class ComparableMixin {
public:
    bool operator !=(ComparableMixin &other) {
        return ~(*static_cast<T*>(this) == static_cast<T&>(other));
    }
    bool operator <(ComparableMixin &other) {
        return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
    }
    bool operator >(ComparableMixin &other) {
        return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
    }
    bool operator >=(ComparableMixin &other) {
        return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
    }
protected:
    ComparableMixin() {}
};

class Integer: public ComparableMixin<Integer> {
public:
 Integer(int i) {
     this->i = i;
 }
 int i;
 bool operator <=(Integer &other) {
     return (this->i <= other.i);
 }
 bool operator ==(Integer &other) {
     return (this->i == other.i);
 }
};
int main() {

    Integer i(0) ;
    Integer j(1) ;
    //ComparableMixin<Integer> c; //compilation error!
    assert (i < j );
    assert (i != j);
    assert (j >  i);
    assert (j >= i);

    return 0;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmol GawaiView Question on Stackoverflow
Solution 1 - C++Henk HoltermanView Answer on Stackoverflow
Solution 2 - C++Nick LewisView Answer on Stackoverflow
Solution 3 - C++GuidobotView Answer on Stackoverflow
Solution 4 - C++anonView Answer on Stackoverflow
Solution 5 - C++Umair AhmedView Answer on Stackoverflow
Solution 6 - C++sean rileyView Answer on Stackoverflow
Solution 7 - C++Oliver HanappiView Answer on Stackoverflow
Solution 8 - C++NimbleView Answer on Stackoverflow
Solution 9 - C++bigdata2View Answer on Stackoverflow