In conversion by constructors, described in the previous section, objects of one type can be implicitly converted to a particular class type. This section describes a means by which you can provide explicit conversions from a given class type to another type. Conversion from a class type is often accomplished using conversion functions. Conversion functions use the following syntax:
Syntax
conversion-function-name :
operator conversion-type-name ()
conversion-type-name :
type-specifier-list ptr-operatoropt
The following example specifies a conversion function that converts type Money
to type double
:
class Money
{
public:
Money();
operator double() { return _amount; }
private:
double _amount;
};
Given the preceding class declaration, the following code can be written:
Money Account;
...
double CashOnHand = Account;
The initialization of CashOnHand
with Account
causes a conversion from type Account
to type double
.
Conversion functions are often called “cast operators” because they (along with constructors) are the functions called when a cast is used. The following example uses a cast, or explicit conversion, to print the current value of an object of type Money
:
cout << (double)Account << endl;
Conversion functions are inherited in derived classes. Conversion operators hide only base-class conversion operators that convert to exactly the same type. Therefore, a user-defined operator int function does not hide a user-defined operator short function in a base class.
Only one user-defined conversion function is applied when performing implicit conversions. If there is no explicitly defined conversion function, the compiler does not look for intermediate types into which an object can be converted.
If a conversion is required that causes an ambiguity, an error is generated. Ambiguities arise when more than one user-defined conversion is available or when a user-defined conversion and a built-in conversion exist.
The following example illustrates a class declaration with a potential ambiguity:
#include <string.h>
class String
{
public:
// Define constructor that converts from type char *.
String( char *s ) { strcpy( _text, s ); }
// Define conversion to type char *.
operator char *() { return _text; }
int operator==( const String &s )
{ return !strcmp( _text, s._text ); }
private:
char _text[80];
};
int main()
{
String s( "abcd" );
char *ch = "efgh";
// Cause the compiler to select a conversion.
return s == ch;
}
In the expression s == ch
, the compiler has two choices and no way of determining which is correct. It can convert ch
to an object of type String
using the constructor and then perform the comparison using the user-defined operator==
. Or it can convert s
to a pointer of type char *
using the conversion function and then perform a comparison of the pointers.
Because neither choice is “more correct” than the other, the compiler cannot determine the meaning of the comparison expression, and it generates an error.