19

The following example is from the book "Inside C++ object model"

class Abstract_base {
public:
    virtual ~Abstract_base () = 0;
    virtual void interface () const = 0;
    virtual const char* mumble () const 
    {
        return _mumble;
    }
protected:
    char *_mumble;
};

The author says if I want to initialize _mumble, the data member of the pure virtual base class, a "protected constructor" should be implemented.

But why protected? And why "public constructor" is not suitable for this class?

Thanks for your answers, and it would be perfect if there's an example.

Wizmann
  • 839
  • 1
  • 9
  • 14
  • Its pure-virtual. The only valid construction of such a thing is via derivation. Said derivation has access to a protected constructor. Nothing else (friends not withstanding) does. It doesn't matter in this case, but at least you know *why*. – WhozCraig Jun 04 '14 at 12:11
  • It would be suitable indeed, but nobody except the derived class could call it anyway. – Quentin Jun 04 '14 at 12:11

5 Answers5

17

It doesn't really matter, since you're not allowed to construct objects of the base class anyway. Making it protected serves only as a reminder of the fact that the class is supposed to be a base class; it's only cosmetics/documentation.

Consider

struct Base {
    virtual ~Base() = 0;
  protected:
    Base() { std::puts("Base constructor"); }
};

Base::~Base() { std::puts("Base destructor"); }

struct Derived : Base {};

int main()
{
    //Base b;   // compiler error
    Derived d;

    Base *b = new Derived();
    delete b;
}

Removing the protected doesn't change the meaning of the program in any way.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
7

Abstract classes and construction of such

It doesn't matter if the constructor is public or protected, since an abstract class cannot be instantiated.

You must inherit from it in order to have it's constructor called, and since the Derived class calls the constructor of the abstract class it doesn't matter what protection level you choose, as long as the Derived class can access it.


One reason that one could possibly have for making it protected is to serve as a reminder that the class must be constructed through inheritance, but honestly that should be clear enough when seeing that it has pure virtual member-functions.


example snippet

struct B {
  virtual void func () = 0;
  virtual ~B () = 0 { };
};

B::~B () { }

struct D : B {
  void func () override;
};

int main () {
  B b; // will error, no matter if Bs ctor is 'public' or 'protected'
       // due to pure virtual member-function

  D d; // legal, D has overriden `void B::func ()`
}
Community
  • 1
  • 1
Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
  • I agree that it should be clear, however for *clarity* purpose it may still help (though then it becomes subjective, of course). – Matthieu M. Jun 04 '14 at 12:19
  • About the "cannot be instantiated" part, the standard says: "no objects of an abstract class can be created except as subobjects of a class derived from it." More info at [this](https://stackoverflow.com/a/42986059/2278206) answer to a related question. – psq May 24 '19 at 12:01
3

A pure virtual class cannot be instantiated, so it doesn't make a difference if the constructor is public or protected.

A public constructor is syntactically correct. However, making it protected will carry a stronger indication that the class cannot be instantiated.

For an example: http://ideone.com/L66Prq

#include <iostream>
using namespace std;

class PublicAbstract {
public:
    PublicAbstract() { }        
    virtual void doThings() =0;
};

class ProtectedAbstract {
protected:
    ProtectedAbstract() { }     
public:
    virtual void doMoreThings() =0;
};

class B: public PublicAbstract {
public:
    void doThings() { } 
};

class C: public ProtectedAbstract {
public:
    void doMoreThings() { } 
};

int main() {
    B b;
    C c;
    return 0;
}
jsantander
  • 4,972
  • 16
  • 27
2

A public constructor would not be very useful, since abstract classes cannot be instantiated in the first place.

A protected constructor makes sense: this way, a derived concrete class can provide its own public constructor that chains to the protected constructor of the base abstract class.

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
0

Protecetd ctor will make sure the ctor gets called by only the classes which derive from Abstract_base.

Public ctor is not suitable because the class contains a pure virtual method! How are you planning to instantiate a pure-virtual class if not via its child classes?

CinCout
  • 9,486
  • 12
  • 49
  • 67