Therefore, that constructor will be used to create the two objects. For jock, the default values of 0 and 0.0 will be used for the second and third arguments. The third declaration matches the default constructor, so temp is constructed using it.
In addition, C++11 offers a class called std::initializer_list that can be used as a type for a function or method parameter. This class can represent a list of arbitrary length, providing all the entries are of the same type or can be converted to the same type. Chapter 16, “The string Class and the Standard Template Library,” will return to this topic.
const Member Functions
Consider the following code snippet:
const Stock land = Stock("Kludgehorn Properties");
land.show();
With current C++, the compiler should object to the second line. Why? Because the code for show() fails to guarantee that it won’t modify the invoking object, which, because it is const, should not be altered. We’ve solved this kind of problem before by declaring a function’s argument to be a const reference or a pointer to const. But there’s a syntax problem: The show() method doesn’t have any arguments for const to qualify. Instead, the object it uses is provided implicitly by the method invocation. What is needed is a new syntax, one that says a function promises not to modify the invoking object. The C++ solution is to place the const keyword after the function parentheses. That is, the show() declaration should look like this:
void show() const; // promises not to change invoking object
Similarly, the beginning of the function definition should look like this:
void stock::show() const // promises not to change invoking object
Class functions declared and defined this way are called const member functions. Just as you should use const references and pointers as formal function arguments whenever appropriate, you should make class methods const whenever they don’t modify the invoking object. We’ll follow this rule from here on out.
Constructors and Destructors in Review
Now that we’ve gone through a few examples of constructors and destructors, you might want to pause and assimilate what has passed. To help you, here is a summary of these methods.
A constructor is a special class member function that’s called whenever an object of that class is created. A class constructor has the same name as its class, but through the miracle of function overloading, you can have more than one constructor with the same name, provided that each has its own signature, or argument list. Also a constructor has no declared type. Usually a constructor is used to initialize members of a class object. Your initialization should match the constructor’s argument list. For example, suppose the Bozo class has the following prototype for a class constructor:
Bozo(const char * fname, const char * lname); // constructor prototype
In this case, you can use it to initialize new objects as follows:
Bozo bozetta = bozo("Bozetta", "Biggens"); // primary form
Bozo fufu("Fufu", "O'Dweeb"); // short form
Bozo *pc = new Bozo("Popo", "Le Peu"); // dynamic object
If C++11 rules are in effect, you can use list initialization instead:
Bozo bozetta = {"Bozetta", "Biggens"}; // C++11
Bozo fufu{"Fufu", "O'Dweeb"} // C++11;
Bozo *pc = new Bozo{"Popo", "Le Peu"}; // C++11
If a constructor has just one argument, that constructor is invoked if you initialize an object to a value that has the same type as the constructor argument. For example, suppose you have this constructor prototype:
Bozo(int age);
Then you can use any of the following forms to initialize an object:
Bozo dribble = bozo(44); // primary form
Bozo roon(66); // secondary form
Bozo tubby = 32; // special form for one-argument constructors
Actually, the third example is a new point, not a review point, but it seemed like a nice time to tell you about it. Chapter 11 mentions a way to turn off this feature because it can lead to unpleasant surprises.
Caution
A constructor that you can use with a single argument allows you to use assignment syntax to initialize an object to a value:
Classname object = value;
This feature can cause problems, but it can be blocked, as described in Chapter 11.
A default constructor has no arguments, and it is used if you create an object without explicitly initializing it. If you fail to provide any constructors, the compiler defines a default constructor for you. Otherwise, you have to supply your own default constructor. It can have no arguments or else it must have default values for all arguments:
Bozo(); // default constructor prototype
Bistro(const char * s = "Chez Zero"); // default for Bistro class
The program uses the default constructor for uninitialized objects:
Bozo bubi; // use default
Bozo *pb = new Bozo; // use default