Программирование >>  Инициализация объектов класса, структура 

1 ... 56 57 58 [ 59 ] 60 61 62 ... 395


extern char *string copy( char* ); const char *pc str;

char *pc = string copy( const cast< char* >( pc str ));

Любое иное использование const cast вызывает ошибку компиляции, как и попытка подобного приведения с помощью любого из трех других операторов.

С применением static cast осуществляются те преобразования, которые могут быть

double d = 97.0;

сделаны неявно, на основе правил по умолчанию:

char ch = static cast< char >( d );

Зачем использовать static cast? Дело в том, что без него компилятор выдаст предупреждение о возможной потере точности. Применение оператора static cast говорит и компилятору, и человеку, читающему программу, что программист знает об этом.

Кроме того, с помощью static cast указатель void* можно преобразовать в указатель определенного типа, арифметическое значение - в значение перечисления (enum), а базовый класс - в производный. (О преобразованиях типов базовых и производных классов говорится в главе 19.)

Эти изменения потенциально опасны, поскольку их правильность зависит от того, какое конкретное значение имеет преобразуемое выражение в данный момент выполнения

enum mumble { first = 1, second, third }; extern int ival; программы:

mumble mums the word = static cast< mumble >( ival );

Трансформация ival в mumble будет правильной только в том случае, если ival равен 1, 2 или 3.

reinterpret cast работает с внутренними представлениями объектов (re-interpret -другая интерпретация того же внутреннего представления), причем правильность этой

complex<double> *pcom;

операции целиком зависит от программиста. Например:

char *pc = reinterpret cast< char* >( pcom );

Программист не должен забыть или упустить из виду, какой объект реально адресуется указателем char* pc. Формально это указатель на строку встроенного типа, и компилятор не будет препятствовать использованию pc для инициализации строки:

string str( pc );



появившийся в C++ вид type (expr);

вид, существовавший в C

Устаревшая форма явного преобразования имеет два вида:

хотя скорее всего такая команда вызовет крах программы.

Это хороший пример, показывающий, насколько опасны бывают явные преобразования типов. Mi можем присваивать указателям одного тина значения указателей совсем другого типа, и это будет работать до тех пор, пока мы держим ситуацию под контролем. Однако, забыв о подразумеваемых деталях, легко допустить ошибку, о которой компилятор не сможет нас предупредить.

Особенно трудно найти подобную ошибку, если явное преобразование типа делается в одном файле, а используется измененное значение в другом.

В некотором смысле это отражает фундаментальный парадокс языка С++: строгая проверка типов призвана не допустить подобных ошибок, в то же время наличие операторов явного преобразования позволяет обмануть компилятор и использовать объекте! разных типов на свой страх и риск. В нашем примере мы отключили проверку типов при инициализации указателя pc и присвоили ему адрес комплексного числа. При инициализации строки str такая проверка производится снова, но компилятор считает, что pc указывает на строку, хотя, на самом-то деле, это не так!

Четыре оператора явного преобразования типов были введены в стандарт С++ как наименьшее зло при невозможности полностью запретить такое приведение. Устаревшая, но до сих пор поддерживаемая стандартом С++ форма явного преобразования выглядит так:

char *pc = (char*) pcom;

Эта запись эквивалентна применению оператора reinterpret cast, однако выглядит не так заметно. Использование операторов xxx cast позволяет четко указать те места в программе, где содержатся потенциально опасные трансформации типов.

Если поведение программы становится ошибочным и непонятным, возможно, в этом виноваты явные видоизменения типов указателей. Использование операторов явного преобразования помогает легко обнаружить места в программе, где такие операции выполняются. (Другой причиной непредсказуемого поведения программы может стать нечаянное уничтожение объекта (delete), в то время как он еще должен использоваться в работе. Mi поговорим об этом в разделе 8.4, когда будем обсуждать динамическое выделение памяти.)

Оператор dynamic cast применяется при идентификации типа во время выполнения (run-time type identification). Mы вернемся к этой проблеме лишь в разделе 19.1.

4.14.4. Устаревшая форма явного преобразования

Операторы явного преобразования типов, представленные в предыдущем разделе, появились только в стандарте С++; раньше использовалась форма, теперь считающаяся устаревшей. Хотя стандарт допускает и эту форму, м1 настоятельно не рекомендуем ею пользоваться. (Только если ваш компилятор не поддерживает новый вариант.)



const char *pc = (const char*) pcom; int ival = (int) 3.14159; extern char *rewrite str( char* ); char *pc2 = rewrite str( (char*) pc );

Вот несколько примеров такого использования:

int addr va1ue = int( siva1 );

Эта форма сохранена в стандарте С++ только для обеспечения обратной совместимости с программами, написанными для С и предыдущих версий С++.

Упражнение 4.21

char cval; int ival; float fval; double dva1;

Даны определения переменных:

unsigned int ui;

(a) cva1 = a + 3;

(b) fval = ui - ival * 1.0;

(c) dva1 = ui * fval;

Какие неявные преобразования типов будут выполнены?

(d) cva1 = ival + fvat + dva1;

Упражнение 4.22

void *pv; int ival;

char *pc; double dval;

Даны определения переменных:

const string *ps;

(a) pv = (void*)ps;

(b) ival = int( *pc );

(c) pv = sdva1;

Перепишите следующие выражения, используя операторы явного преобразования типов:

(d) pc = (char*) pv;

(type) expr;

и может применяться вместо операторов static cast, const cast и reinterpret cast.



1 ... 56 57 58 [ 59 ] 60 61 62 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.004
При копировании материалов приветствуются ссылки.
Яндекс.Метрика