steffen
steffen

Reputation: 8958

Protected constructor to make base class not instantiable

Is it good practice to make a base class constructor protected if I want to avoid instances of it? I know that I could as well have a pure virtual dummy method, but that seems odd...

Please consider the following code:

#include <iostream>

using std::cout;
using std::endl;

class A 
{
protected:
    A(){};
public:
    virtual void foo(){cout << "A\n";};
};

class B : public A
{
public:
    void foo(){cout << "B\n";}
};

int main()
{
    B b;
    b.foo();
    A *pa = new B;
    pa->foo();

    // this does (and should) not compile:
    //A a;
    //a.foo();
    return 0;
}

Is there a disadvantage or side-effect, that I don't see?

Upvotes: 7

Views: 12168

Answers (4)

Arne Mertz
Arne Mertz

Reputation: 24576

What you want to achieve is normally done via the destructor, instead of the constructors, just beacause you can steer the behavior you need with that one function instead of having to deal with it with every new constructor you write. It's a common coding style/guideline, to

  • make the destructor public, if you want to allow instances of the class. Often those classes are not meant to be inherited from.
  • make the destructor pure virtual and public, if you want to use and delete the class in a polymorphic context but don't want to allow instances of the class. In other words, for base classes that are deleted polymorphcally.
  • make the destructor nonvirtual and protected, if you don't want to allow instances of the class and don't want to delete its derivates polymorphically. Normally, you then don't want to use them polymorphically at all, i.e. they have no virtual functions.

Which of the latter two you chose is a design decision and cannot be answered from your question.

Upvotes: 2

Neil Kirk
Neil Kirk

Reputation: 21763

Make the destructor pure virtual. Every class has a destructor, and a base class should usually have a virtual destructor, so you are not adding a useless dummy function.

Take note that a pure virtual destructor must have a function body.

class AbstractBase
{
public:
    virtual ~AbstractBase() = 0;
};
inline AbstractBase::~AbstractBase() {}

If you don't wish to put the destructor body in the header file, put it in the source file and remove inline keyword.

Upvotes: 1

villekulla
villekulla

Reputation: 1085

It is common practice to make base class constructors protected. When you have a pure-virtual function in your base class, this is not required, as you wouldn't be able to instantiate it.

However, defining a non-pure virtual function in a base class is not considered good practice, but heavily depends on your use case and does not harm.

There isn't any disadvantage or side-effect. With a protected constructor you just tell other developers that your class is only intended to be used as a base.

Upvotes: 10

6502
6502

Reputation: 114461

It does what you're asking.

However I'm not sure what you are gaining with it. Someone could just write

struct B : A {
   // Just to workaround limitation imposed by A's author
};

Normally it's not that one adds nonsense pure-virtual functions to the base class... it's that there are pure virtual functions for which no meaningful implementation can be provided at the base level and that's why they end up being pure virtual.

Not being able to instantiate that class comes as a nice extra property.

Upvotes: 1

Related Questions