Discussion
Team LiB
Previous Section Next Section

Discussion

In C++, a complete object is constructed one base class at a time.

Say we have a base class B and a class D derived from B. When constructing a D object, while executing B's constructor, the dynamic type of the object under construction is B. In particular, a call to a virtual function B::Fun will hit B's definition of Fun, regardless of whether D overrides it or not; and that's a good thing, because calling a D member function when the D object's members haven't even been initialized yet would lead to chaos. Only after the construction of B has completed is D's constructor body executed and its identity as a D established. As a rule of thumb, keep in mind that during B's construction there is no way to tell whether the B is a standalone object or a base part of some other further-derived object; virtually-acting virtual functions would be such a "way."

To add insult to injury, a call from a constructor to a pure virtual function that isn't defined at all has, well, undefined behavior. Such code is therefore not only confusing, but it is also more fragile in face of maintenance.

On the other hand, some designs ask for "post-construction," that is, a virtual function that must be invoked right after the full object has been constructed. Some techniques for this are shown in the References. Here's a non-exhaustive list of options:

  • Pass the buck: Just document that user code must call the post-initialization function right after constructing an object.

  • Post-initialize lazily: Do it during the first call of a member function. A Boolean flag in the base class tells whether or not post-construction has taken place yet.

  • Use virtual base class semantics: Language rules dictate that the constructor most-derived class decides which base constructor will be invoked; you can use that to your advantage. (See [Taligent94].)

  • Use a factory function: This way, you can easily force a mandatory invocation of a post-constructor function. (See Examples.)

No post-construction technique is perfect. The worst dodge the whole issue by simply asking the caller to invoke the post-constructor manually. Even the best require a different syntax for constructing objects (easy to check at compile time) and/or cooperation from derived class authors (impossible to check at compile time).

    Team LiB
    Previous Section Next Section