Chapter 4 described constructors, the functions that create objects. A constructor that takes only one parameter is considered a conversion function; it specifies a conversion from the type of the parameter to the type of the class. For example, suppose you specify a default value for the denominator parameter of the Fraction constructor, as follows:
class Fraction
{
public:
Fraction( long num, long den = 1 );
// ...
};
This constructor not only lets you initialize a Fraction object using only one number, it also lets you assign integers to a Fraction object directly. For example:
Fraction a( 2 ); // Equivalent to Fraction a( 2 , 1 );
a = 7; // Equivalent to a = Fraction( 7 );
// a = Fraction( 7, 1 );
In the above statement, the compiler uses the single-argument constructor to implicitly convert an integer into a temporary Fraction object, and then uses the object for the assignment. Similarly, if you pass an integer to a function that expects a Fraction object, the integer is converted before the function is called.
To be more precise, when you pass the Fraction constructor an integer, the compiler actually performs a standard conversion and a user-defined conversion at once. For example:
a = 7; // int -> long -> Fraction
The compiler first performs a standard conversion to make the integer into a long integer. Then it converts the long integer into a Fraction and performs the assignment.
One result of defining an implicit conversion is that one operator function can handle several different types of expression. Suppose you define just one operator+ function for the Fraction class:
class Fraction
{
public:
Fraction( long num, long den = 1 );
friend Fraction operator+( const Fraction &first,
const Fraction &second );
// ...
};
The combination of that constructor and that operator function accepts all of these expressions:
Fraction a,
b( 2, 3 ),
c( 4, 5 );
a = b + c; // Okay as is
a = b + 1234; // a = b + Fraction( 1234 );
a = 1234 + b; // a = Fraction( 1234 ) + b;
a = 1234 + 5678; // a = Fraction( 6912 );
When the compiler evaluates each expression, it looks for an operator+ function that fits. If it can't find one, it tries to convert one or more of the operands so that they match the operator+ function that does exist. As a result, the compiler converts the integers into Fraction objects, and performs the addition on them.
Notice that in the last assignment statement the compiler does not convert the integers into Fraction objects. It is able to add the integers directly. The compiler then converts the resulting sum into a temporary Fraction object to perform the assignment.
A single-argument constructor defines an implicit conversion that turns instances of other types into objects of your class, so that your class is the target of the conversion. You can also define an implicit conversion that turns objects of your class into instances of other types, making your class the source of the conversion. To do this, you define a “conversion operator.”