C++ provides implicit type conversion, as described in Chapter 3, “Standard Conversions.” You can also specify explicit type conversions when you need more precise control of the conversions applied.
Explicit Type Conversion Operator
C++ allows explicit type conversion using a syntax similar to the function-call syntax. A simple-type-name followed by an expression-list enclosed in parentheses constructs an object of the specified type using the specified expressions. The following example shows an explicit type conversion to type int:
int i = int( d );
The following example uses the Point class defined in “Function Call Results” with a few modifications.
#include <iostream.h>
class Point
{
public:
// Define default constructor.
Point() { _x = _y = 0; }
// Define another constructor.
Point( int X, int Y ) { _x = X; _y = Y; }
// Define “accessor” functions as
// reference types.
unsigned& x() { return _x; }
unsigned& y() { return _y; }
void Show() { cout << “x = ” << _x << “, ”
<< “y = ” << _y << “\n”; }
private:
unsigned _x;
unsigned _y;
};
int main()
{
Point Point1, Point2;
// Assign Point1 the explicit conversion
// of ( 10, 10 ).
Point1 = Point( 10, 10 );
// Use x() as an l-value by assigning an explicit
// conversion of 20 to type unsigned.
Point1.x() = unsigned( 20 );
Point1.Show();
// Assign Point2 the default Point object.
Point2 = Point();
Point2.Show();
return 0;
}
The output from this program is:
20, 10
0, 0
Although the above example demonstrates explicit type conversion using constants, the same technique works to perform these conversions on objects. The following code fragment demonstrates this:
int i = 7;
float d;
d = float( i );
Explicit type conversions can also be specified using the “cast” syntax. The previous example, rewritten using the cast syntax, follows:
d = (float)i;
Both cast and function-style conversions have the same results when converting from single values. However, in the function-style syntax, you can specify more than one argument for conversion. This difference is important for user-defined types. Consider a Point class, and its conversions:
struct Point
{
Point( short x, short y ) { _x = x; _y = y; }
...
short _x, _y;
};
...
Point pt = Point( 3, 10 );
The example above, which uses function-style conversion, shows how to convert two values (one for x and one for y) to the user-defined type Point.
Important:
Explicit type conversions override the C++ compiler's built-in type checking. These conversions should be used with care.
cast-expression:
unary-expression
(type-name)cast-expression
The cast notation must be used for conversions to types that do not have a simple-type-name (pointer or reference types, for example). Conversion to types that can be expressed with a simple-type-name can be written in either form. See “Type Specifiers” in Chapter 6, on topic for more information about what constitutes a simple-type-name.
Type definition within casts is illegal. Therefore, the following code generates an error:
int AnAction = 2;
Action ThisAction = (enum Action{ Deposit=1, Withdraw,
GetBalance }) AnAction;
Explicit conversions from a given type to another type can be done if the conversion can be done using standard conversions. The results are the same.
In addition, the conversions described in the following sections are legal; any other conversions not explicitly defined by the user (for a class type) are illegal.
A value of integral type can be explicitly converted to a pointer if the pointer is large enough to hold the integral value. A pointer that is converted to an integral value can be converted back to a pointer; its value is the same. This identity is given by the following (where p represents a pointer of any type):
p == (type *) integral-conversion( p )
Note that with explicit conversions, the compiler does not check whether the converted value fits in the new type except when converting from pointer to integral type or vice versa.
A pointer to one object type can be explicitly converted to a pointer of another object type. A pointer declared as void * is considered a pointer to any object type.
A pointer to a base class can be explicitly converted to a pointer to a derived class as long as these conditions are met:
There is an unambiguous conversion.
The base class is not declared as virtual at any point.
Because conversion to type void * can change the representation of an object, there is no guarantee that the conversion type1* void * type2* is equivalent to the conversion type1* type2* (which is a change in value only).
When such a conversion is performed, the result is a pointer to the subobject of the original object representing the base class.
See Chapter 9, “Derived Classes,” for more information about ambiguity and virtual base classes.
A pointer to a function can be explicitly converted to a pointer-to-object type, provided the pointer to the object has enough bits. This restriction is sensitive to memory-model selection; as a result, memory-model selection can change the size of pointers to functions. Code that works in small model can fail in medium model, as shown in this example:
void func();
int main()
{
int iPtr;
void (*fPtr)() = func;
iPtr = (int)fPtr;
return 0;
}
In small model (for the 16-bit compiler), both objects of type int and pointers to functions are 16 bits. However, changing to medium model changes pointers to functions to 32-bit pointers, causing a compilation error.
C++ allows explicit conversions of pointers to objects or functions to type void *.
Pointers to object types can be explicitly converted to pointers to functions if the function pointer type has enough bits to accommodate the pointer to object type.
A pointer to a const object can be explicitly converted to a pointer not of const type. The result of this conversion points to the original object. An object of const type, or a reference to an object of const type, can be cast to a reference to a nonconst type. The result is a reference to the original object. The original object was probably declared as const because it was to remain constant across the duration of the program. Therefore, an explicit conversion defeats this safeguard, allowing modification of such objects. The behavior in such cases is undefined.
A pointer to an object of volatile type can be cast to a pointer to a nonvolatile type. The result of this conversion refers to the original object. Similarly, an object of volatile type can be cast to a reference to a nonvolatile type.
The null pointer (0) is converted into itself.
Converting to a Forward-Reference Class Type
A class that has been declared but not yet defined (a forward reference) can be used in a pointer cast. In this case, the compiler returns a pointer to the original object, not to a subobject as it might if the class's relationships were known.
Any object whose address can be converted to a given pointer type can also be converted to the analogous reference type. For example, any object whose address can be converted to type char * can also be converted to type char &. No constructors or class conversion functions are called to make a conversion to a reference type.
Objects or values can be converted to class-type objects only if a constructor or conversion operator has been provided specifically for this purpose. For more information about these user-defined functions, see “Conversion Constructors” in Chapter 11, on topic .
Conversion of a reference to a base class, to a reference to a derived class (and vice versa) is done the same way as for pointers.
A cast to a reference type results in an l-value. The results of casts to other types are not l-values. Operations performed on the result of a pointer or reference cast are still performed on the original object.
Converting Among Pointer-to-Member Types
A pointer to a member can be converted to a different pointer-to-member type subject to these rules: Either the pointers must both be pointers to members in the same class or they must be pointers to members of classes, one of which is derived unambiguously from the other. When converting pointer-to-member functions, the return and argument types must match.