Why does a purely virtual/abstract class require a constructor, in particular for protected const member variables?

ticster picture ticster · Feb 22, 2012 · Viewed 13.7k times · Source

I have a purely virtual class defined as such:

class BaseClass {
 protected:
  const int var;
 public:
  void somefun() = 0; // what I mean by a purely virtual class
  // stuff...
};

If I don't add a constructor defined as such:

BaseClass(const int & VAR) : var(VAR) {};

that I would have to subsequently use in ever derived class, my derived class can't initialize the const variable var to whichever value it wants to. Now I actually understand what's going on here. Before constructing a derived class, a constructor of the base class is called, at which point const member variables must be initialized. My question is not a "how do I make my code work" kind of question, that's already been done. My question is about why the compiler thinks it's necessary. For a purely virtual class, shouldn't I be allowed to write something like:

class DerivedClass : BaseClass {
 public:
  DerivedClass() : var(SOME_VALUE) {};
}

If the compiler knows that a call to a BaseClass constructor will necessarily be followed by a call to some derived class constructror (since an object of abstract type can never be instantiated) shouldn't it give us a bit more leeway?

Is this all a consequence of how C++ chooses to get around the Diamond problem? Even if that was the case, shouldn't the compiler at least somehow allow for the possibility that const member variable of purely virtual functions will be defined in derived classes? Is that too complicated or does that mess with the C++ solution to the Diamond problem?

Thanks for the help everyone.

Answer

Mike Seymour picture Mike Seymour · Feb 22, 2012

It's not "purely virtual" (whatever you mean by that) - it contains a data member.

Class members can only be initialised by the initialiser list of a constructor of that class, not of a derived class. That's how object initialisation is specified: all members that are initialised, are initialised before the constructor body begins.

Constant objects must be initialised, since they can't be assigned a value later.

Therefore, a class with a constant data member must initialise it in each constructor.