OOPortal OOPortal
Programming C++  «Prev  Next»
Lesson 8 Casts
ObjectiveC++ improves casts by making them safer.

C++ improves casts by making them safer

Casts, in general, should be avoided. They are usually a shortcut for avoiding extra coding or an efficiency hack for avoiding extra processing. If you must cast, use C++'s static_cast instead of the unrestricted forms of cast used in C and in older C++ systems.

static_cast

If i is an int, then
static_cast<double>(i)

will cast the value of i so that the expression has type double. The variable i remains unchanged.
The static_cast should be used for a conversion that is well-defined, portable, and invertible.

Examples

Here are several examples of using static_cast.

Casts to avoid

C++ does provide a means for representation- or system-dependent casts using reinterpret_cast.
These types of casts are undesirable and generally should be avoided.
You should also avoid the unrestricted forms of casts that are used in C and in older C++ systems.

Explicit Type Conversion

To convert the value of an expression to a given type, you write the following:
static_cast<type_to_convert_to>(expression)

The static_cast keyword reflects the fact that the cast is checked statically; that is, when the code is compiled. Later, when you get to deal with classes, you will meet dynamic casts, where the conversion is checked dynamicall. That is, when the program is executing. The effect of the cast is to convert the value that results from evaluating expression to the type that you specify between the angle brackets. The expression can be anything from a single variable to a complex expression involving lots of nested parentheses. You could eliminate the warning that arises from the assignment in the previous section by writing it as:
y = static_cast<int>(z); // No compiler warning this time...


Here is another example of the use of static_cast<>():
double value1 {10.5};
double value2 {15.5};
int whole_number {static_cast<int>(value1) + static_cast<int>(value2)};
The initializing value for whole_number is the sum of the integral parts of value1 and value2, so they are each explicitly cast to type int.
whole_number will therefore have the initial value 25. The casts do not affect the values stored in value1 and value2, which will remain as 10.5 and 15.5, respectively. The values 10 and 15 produced by the casts are just stored temporarily for use in the calculation and then discarded. Although both casts cause a loss of information, the compiler always assumes that you know what you are doing when you explicitly specify a cast. Of course, the value of whole_number would be different if you wrote:
int whole_number {static_cast<int>(value1 + value2)};

The result of adding value1 and value2 will be 26.0, which results in 26 when converted to type int. The compiler will not insert implicit narrowing conversions for values in an initializer list so the statement will not compile without the explicit type conversion. Generally, the need for explicit casts should be rare, particularly with basic types of data. If you have to include a lot of explicit conversions in your code, it is often a sign that you could choose more suitable types for your variables. Still, there are circumstances when casting is necessary, so let us look at a simple example. This example converts a length in yards as a decimal value to yards, feet, and inches.

// Using Explicit Type
#include <iostream >
int main(){
 const unsigned int feet_per_yard{3};
 const unsigned inches_per_foot{12};
 double length {}; // Length as decimal yards
 unsigned int yards{}; // Whole yards
 unsigned int feet {}; // Whole feet
 unsigned int inches {}; // Whole inches
 std::cout << "Enter a length in yards as a decimal: ";
 std::cin >> length;
 // Get the length as yards, feet, and inches
 yards = static_cast<unsigned int>(length);
 feet = static_cast<unsigned int>((length - yards)*feet_per_yard);
 inches = static_cast<unsigned int>
 (length*feet_per_yard *inches_per_foot) % inches_per_foot;
 std::cout << length << " yards converts to "
 << yards << " yards "
 << feet << " feet "
 << inches << " inches." << std:: endl;
}

Typical output from this program will be:
Enter a length in yards as a decimal: 2.75
2.75 yards converts to 2 yards 2 feet 3 inches.