I\'m currently having a discussion with my teacher about class design and we came to the point of Initialize()
functions, which he heavily promotes. Example:
I"m against 'double initialization' in C++ whatsoever.
Arguments against constructors:
- can't be overridden by derived classes
- can't call virtual functions
If you have to write such code, it means your design is wrong (e.g. MFC). Design your base class so all the necessary information that can be overridden is passed through the parameters of its constructor, so the derived class can override it like this:
Derived::Derived() : Base(GetSomeParameter())
{
}
Ignoring the RAII implications, which others have adequately covered, a virtual initialization method greatly complicates your design. You can't have any private data, because for the ability to override the initialization routine to be at all useful, the derived object needs access to it. So now the class's invariants are required to be maintained not only by the class, but by every class that inherits from it. Avoiding that sort of burden is part of the point behind inheritance in the first place, and the reason constructors work the way they do with regard to subobject creation.
A voice of dissension is in order here.
You might be working in an environment where you have no choice but to separate construction and initialization. Welcome to my world. Don't tell me to find a different environment; I have no choice. The preferred embodiment of the products I create is not in my hands.
Tell me how to initialize some aspects of object B with respect to object C, other aspects with respect to object A; some aspects of object C with respect to object B, other aspects with respect to object A. The next time around the situation may well be reversed. I won't even get into how to initialize object A. The apparently circular initialization dependencies can be resolved, but not by the constructors.
Similar concerns goes for destruction versus shutdown. The object may need to live past shutdown, it may need to be reused for Monte Carlo purposes, and it might need to be restarted from a checkpoint dumped three months ago. Putting all of the deallocation code directly in the destructor is a very bad idea because it leaks.
Forget about the Initialize()
function - that is the job of the constructor.
When an object is created, if the construction passed successfully (no exception thrown), the object should be fully initialized.
One argument for preferring initialization in the constructor: it makes it easier to ensure that every object has a valid state. Using two-phase initialization, there's a window where the object is ill-formed.
One argument against using the constructor is that the only way of signalling a problem is through throwing an exception; there's no ability to return anything from a constructor.
Another plus for a separate initialization function is that it makes it easier to support multiple constructors with different parameter lists.
As with everything this is really a design decision that should be made with the specific requirements of the problem at hand, rather than making a blanket generalization.
This is a terrible, terrible idea. Ask yourself- what's the point of the constructor if you just have to call Initialize()
later? If the derived class wants to override the base class, then don't derive.
When the constructor finishes, it should make sense to use the object. If it doesn't, you've done it wrong.