Discussion
Team LiB
Previous Section Next Section

Discussion

Consider the code below:



class Employee {


 string email_, firstName_, lastName_;





public:


 Employee( const char* firstName, const char* lastName )


  : firstName_(firstName), lastName_(lastName)


  , email_(firstName_ + "." + lastName_ + "@acme.com") {}


};



This code harbors a bug that's as pernicious as it is hard to spot. Because email_ is declared before first_ and last_ in the class definition, it will be initialized first and will attempt to use the other not-yet-initialized fields. Worse, if the constructor's definition is in a separate file, the long-distance influence that the order of member variable declarations has over the constructor's correctness will be even harder to spot.

The reason for this language design decision is to ensure there is a unique order to destroy members; otherwise, the destructor would have to destroy objects in different orders, depending on the constructor that built the object. The bookkeeping overhead for that was deemed unacceptable.

The solution is to always write member initializers in the same order in which the members are declared. That way, any illegal dependency will become obvious. Better yet, strive to not have one member's initialization depend on other members.

Many compilers (but not all) will issue a warning if you break this rule.

    Team LiB
    Previous Section Next Section