4.14. Преобразования типов
4.14. Преобразования типов
Представим себе следующий оператор присваивания:
int ival = 0;
// обычно компилируется с предупреждением
ival = 3.541 + 3;
В результате ival получит значение 6. Вот что происходит: мы складываем литералы разных типов – 3.541 типа double и 3 типа int. C++ не может непосредственно сложить подобные операнды, сначала ему нужно привести их к одному типу. Для этого существуют правила преобразования арифметических типов. Общий принцип таков: перейти от операнда меньшего типа к большему, чтобы не потерять точность вычислений.
В нашем случае целое значение 3 трансформируется в тип double, и только после этого производится сложение. Такое преобразование выполняется независимо от желания программиста, поэтому оно получило название неявного преобразования типов.
Результат сложения двух чисел типа double тоже имеет тип double. Значение равно 6.541. Теперь его нужно присвоить переменной ival. Типы переменной и результата 6.541 не совпадают, следовательно, тип этого значения приводится к типу переменной слева от знака равенства. В нашем случае это int. Преобразование double в int производится автоматически, отбрасыванием дробной части (а не округлением). Таким образом, 6.541 превращается в 6, и этот результат присваивается переменной ival. Поскольку при таком преобразовании может быть потеряна точность, большинство компиляторов выдают предупреждение.
Так как компилятор не округляет числа при преобразовании double в int, при необходимости мы должны позаботиться об этом сами. Например:
double dva1 = 8.6;
int iva1 = 5;
ival += dva1 + 0.5; // преобразование с округлением
При желании мы можем произвести явное преобразование типов:
// инструкция компилятору привести double к int
ival = static_cast int ( 3.541 ) + 3;
В этом примере мы явно даем указание компилятору привести величину 3.541 к типу int, а не следовать правилам по умолчанию.
В этом разделе мы детально обсудим вопросы и неявного (как в первом примере), и явного преобразования типов (как во втором).
4.14.1. Неявное преобразование типов
Язык определяет набор стандартных преобразований между объектами встроенного типа, неявно выполняющихся компилятором в следующих случаях:
арифметическое выражение с операндами разных типов: все операнды приводятся к наибольшему типу из встретившихся. Это называется арифметическим преобразованием. Например:
int ival = 3;
double dva1 = 3.14159;
// ival преобразуется в double: 3.0
ival + dva1;
*
присваивание значения выражения одного типа объекту другого типа. В этом случае результирующим является тип объекта, которому значение присваивается. Так, в первом примере литерал 0 типа int присваивается указателю типа int*, значением которого будет 0. Во втором примере double преобразуется в int.
// 0 преобразуется в нулевой указатель типа int*
int *pi = 0;
// dva1 преобразуется в int: 3
ivat = dva1;
*
передача функции аргумента, тип которого отличается от типа соответствующего формального параметра. Тип фактического аргумента приводится к типу параметра:
extern double sqrt( double );
// 2 преобразуется в double: 2.0
cout "Квадратный корень из 2: " sqrt( 2 )
endt;
*
возврат из функции значения, тип которого не совпадает с типом возвращаемого результата, заданным в объявлении функции. Тип фактически возвращаемого значения приводится к объявленному. Например:
double difference( int ivati, int iva12 )
{
// результат преобразуется в double
return ivati - iva12;
}
*