Heron-Centric: Ruminations of a Language Designer Two Stage Construction in C++ versus Initializing Constructors by Christopher Diggins April 26, 2005
I am working on the OOTL collections library right now, and I am facing a design dilemma: is it better to use initializing constructors or to use two stage construction.
In C++ there is one huge imperfection which has really got me frustrated lately, the fact that constructors are not inherited. I think this was done because C++ uses constructors as implicit cast operators (this in of itself is another big imperfection!)
I am trying to construct sophisticated object oriented libraries with many levels of inheritance, and the fact that I have to write out explicitly trivial constructors over and over again is driving me nuts.
In general I can't help but wonder, what is so bad about two stage construction. Here is my list of pros and cons:
Possible performance penalty, when default initialization steps are taken unneccessarily.
Classes which should not be default constructed will require checks requiring an initialization variable to make sure that they are initialized before used.
Designs with deep inheritance trees can be expressed with significantly less code
Wrapper classes (e.g. contract classes or veneers [see Matthew Wilson's book Imperfect C++ Chapter 21]) are much easier to implement, and become more viable
There is no chance of programmer errors within multiple initialization lists (see Matthew Wilson's book Imperfect C++ section 2.3.2 on Member Ordering Dependencies)
No chance of incorrect casts silently generated by the compiler
Easier to trace, debug and understand code
Con #1 should be a non-issue much of the time, because a sophisticated optimizer can easily remove redundant operations. Con #2 can be dealt with relative ease and efficiency using contracts to verify the initializing. Interestingly enough contracts are much easier to implement if classes don't have initializing constructors.
The reason all of this has become such an issue for me is that I want to seperate the OOTL implementation of standard classes (like lists or arrays) into four levels: implementation, contract, extension, and final, where each one inherits from the previous.
The implementation class represents a basic implementation of the core data type.
the contract is a class which wraps (i.e. inherits from) the implementation and provides verification of the preconditions, postconditions and invariants
The extension wraps the contract adding extra utility functions which can be trivially derived from the core implementation functions (e.g. syntactic sugar)
The final version is a class which conditionally (depending on compile-time constants) creates a class for the user to use, which either applies the contract to the implementation or not
So for example where the STL defines a single class like std::string, the OOTL will be creating a hierarchy of four classes: ootl::string_impl, ootl::string_contract, ootl::string_extensions, ootl::string. Clearly writing out constructors over and over is not something that I look forward to, nor does it make sense from an engineering standpoint.
This is where I am at so far. Any thoughts, comments or additions would be welcome!
Have an opinion?
Readers have already posted
about this weblog entry. Why not
If you'd like to be notified whenever Christopher Diggins adds a new entry to his weblog, subscribe to his RSS feed.
Christopher Diggins is a software developer and freelance writer. Christopher loves programming, but is eternally frustrated by the shortcomings of modern programming languages. As would any reasonable person in his shoes, he decided to quit his day job to write his own ( www.heron-language.com ). Christopher is the co-author of the C++ Cookbook from O'Reilly. Christopher can be reached through his home page at www.cdiggins.com.