Stubborn Pascal and ADAProgramYou will often miss the function of setting the upper and lower limits of array subscripts. That is, the range of objects under the array can be set to 10 to 20, not necessarily 0 to 10. Senior C programmers will insist on counting from 0, but it is easy to find a way to meet the requirements of those who are still using begin/end, you only need to define an array class template:
Template <class T>
Class Array {
Public:
Array (INT lowbound, int highbound );
...
PRIVATE:
Vector <t> data; // The array data is stored in the vector object.
// For vector templates, see section 49
Size_t size; // number of elements in the array
Int lbound, hbound; // lower limit, Upper Limit
};
Template <class T>
Array <t>: array (INT lowbound, int highbound)
: Size (highbound-lowbound + 1 ),
Lbound (lowbound), hbound (highbound ),
Data (size)
{}
The constructor checks the validity of parameters to ensure that highbound must at least be greater than or equal to lowbound, but here is a bad error: even if the upper and lower limits of the array are valid, no one knows the number of elements in data.
"How is this possible ?" I heard you calling. "I initialized the size carefully before passing it to the vector constructor !" Unfortunately, you didn't -- you just wanted to do this, but didn't follow the game rules: Class Members were initialized in the order they were declared in the class, it has nothing to do with the order they are listed in the member initialization list. In the class generated using the preceding array template, data is always initialized first, followed by size, lbound, and hbound.
It seems unreasonable, but there is a reason to do so. See the following situation:
Class wacko {
Public:
Wacko (const char * s): S1 (s), S2 (0 ){}
Wacko (const wacko & RHs): S2 (RHS. S1), S1 (0 ){}
PRIVATE:
String S1, S2;
};
Wacko W1 = "Hello world! ";
Wacko W2 = W1;
If members are initialized in the order they appear on the initialization list, the data members in W1 and W2 are created in different order. We know that for all members of an object, the order in which their destructor are called is always the opposite of the order they are created in the constructor. Then, if the above conditions (that is, the members are initialized in the order they appear on the initialization list) are allowed, the compiler will track the initialization order of each object's members, to ensure that their destructor are called in the correct order. This results in expensive costs. Therefore, to avoid this sale, all objects of the same type Process members in the same order during creation (construction) and destruction (analysis, regardless of the Order of the members in the initialization list.
In fact, if you go into it, you will find that the initialization of non-static data members only follows the above rules. Static data members act like global and namespace objects, so they are initialized only once (see section 47 ). In addition, the base class data member is always initialized before the data member of the derived class. Therefore, when using inheritance, the base class initialization should be listed at the beginning of the member initialization list. (If multi-inheritance is used, the initialization sequence of the base class is the same as that of the derived class, and their order in the member initialization list is ignored. There are many considerations for using multi-inheritance. Clause 43 puts forward many suggestions on the issues that should be considered for multi-inheritance .)
The basic one is: If you want to figure out how the object is initialized, make sure that the order listed by the members in your initialization list is the same as that declared by the members in the class.