|
Программирование >> Инициализация объектов класса, структура
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.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.004
При копировании материалов приветствуются ссылки. |