taft = 325; // same as taft = Stonewt(325);
cout << "After dinner, the celebrity weighed ";
incognito.show_stn();
cout << "After dinner, the President weighed ";
taft.show_lbs();
display(taft, 2);
cout << "The wrestler weighed even more.\n";
display(422, 2);
cout << "No stone left unearned\n";
return 0;
}
void display(const Stonewt & st, int n)
{
for (int i = 0; i < n; i++)
{
cout << "Wow! ";
st.show_stn();
}
}
Here is the output of the program in Listing 11.18:
The celebrity weighed 19 stone, 9 pounds
The detective weighed 20 stone, 5.7 pounds
The President weighed 302 pounds
After dinner, the celebrity weighed 19 stone, 10.8 pounds
After dinner, the President weighed 325 pounds
Wow! 23 stone, 3 pounds
Wow! 23 stone, 3 pounds
The wrestler weighed even more.
Wow! 30 stone, 2 pounds
Wow! 30 stone, 2 pounds
No stone left unearned
Program Notes
Note that when a constructor has a single argument, you can use the following form when initializing a class object:
// a syntax for initializing a class object when
// using a constructor with one argument
Stonewt incognito = 275;
This is equivalent to the other two forms shown earlier:
// standard syntax forms for initializing class objects
Stonewt incognito(275);
Stonewt incognito = Stonewt(275);
However, the last two forms can also be used with constructors that have multiple arguments.
Next, note the following two assignments from Listing 11.18:
incognito = 276.8;
taft = 325;
The first of these assignments uses the constructor with a type double argument to convert 276.8 to a type Stonewt value. This sets the pounds member of incognito to 276.8. Because it uses the constructor, this assignment also sets the stone and pds_left members of the class. Similarly, the second assignment converts a type int value to type double and then uses Stonewt(double) to set all three member values in the process.
Finally, note the following function call:
display(422, 2); // convert 422 to double, then to Stonewt
The prototype for display() indicates that its first argument should be the Stonewt object. (Either a Stonewt or a Stonewt & formal parameter matches a Stonewt argument.) Confronted with an int argument, the compiler looks for a Stonewt(int) constructor to convert the int to the desired Stonewt type. Failing to find that constructor, the compiler looks for a constructor with some other built-in type to which an int can be converted. The Stonewt(double) constructor fits the bill. So the compiler converts int to double and then uses Stonewt(double) to convert the result to a Stonewt object.
Conversion Functions
Listing 11.18 converts a number to a Stonewt object. Can you do the reverse? That is, can you convert a Stonewt object to a double value, as in the following?
Stonewt wolfe(285.7);
double host = wolfe; // ?? possible ??
The answer is that you can do this—but not by using constructors. Constructors only provide for converting another type
Conversion functions are user-defined type casts, and you can use them the way you would use a type cast. For example, if you define a Stonewt-to-double conversion function, you can use the following conversions:
Stonewt wolfe(285.7);
double host = double (wolfe); // syntax #1
double thinker = (double) wolfe; // syntax #2
Or you can let the compiler figure out what to do:
Stonewt wells(20, 3);
double star = wells; // implicit use of conversion function
The compiler, noting that the right side is type Stonewt and the left side is type double, looks to see if you’ve defined a conversion function that matches this description. (If it can’t find such a definition, the compiler generates an error message to the effect that it can’t assign a Stonewt to a double.)
So how do you create a conversion function? To convert to type
operator
Note the following points:
• The conversion function must be a class method.
• The conversion function must not specify a return type.
• The conversion function must have no arguments.
For example, a function to convert to type double would have this prototype:
operator double();
The
To add functions that convert stone_wt objects to type int and to type double, then, requires adding the following prototypes to the class declaration:
operator int();
operator double();
Listing 11.19 shows the modified class declaration.
Listing 11.19. stonewt1.h
// stonewt1.h -- revised definition for the Stonewt class
#ifndef STONEWT1_H_
#define STONEWT1_H_
class Stonewt
{