Bjarne Stroustrup writes:
When defining the functions for a class with a virtual base, the programmer in general cannot know whether the base will be shared with other derived classes. This can be a problem when implementing a service that requires a base class function to be called exactly once.
I don’t understand this statement.
What possible problems can creep in?
To explain it he gives strange example
class A { // no constructor
// ...
};
class B {
public:
B(); // default constructor
// ...
};
class C {
public:
C(int); // no default constructor
};
class D: virtual public A, virtual public B, virtual public C
{
D() { /*... */ } // error: no default constructor for C
D(int i) : C(i i) { /*... */ }; // ok
// ...
};
Is it relevant here??
Imagine you have a virtual base class that needs to be initialized by calling
.initialize(42), exactly once. The point is, you don’t which derived class should call it.The correct answer in this case is “sometimes here, sometimes there”, but you don’t know which is the case (depends on which class is the most derived subobject).
C++ solves this issue for constructors, st. the constructors for all virtual bases are called exactly once in the most derived subobject’s constructor; any constructor in the hierarchy must be prepared to call the virtual base constructor (although at runtime, it might not happen).