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

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


char cval;

bool found;

enum mumble { ml, m2, m3 } mval; unsigned long ulong;

В следующем выражении

cval + ulong; ulong + found; mval + ulong;

перед определением типа результата cval, found и mval преобразуются в int.

После приведения к целому сравниваются получившиеся типы операндов. Если один из них имеет тип unsigned long, то остальные будут того же типа. В нашем примере все три объекта, прибавляемые к ulong, приводятся к типу unsigned long.

Если в выражении нет объектов unsigned long, но есть объекты типа long, тип

char cval;

long lval;

cval и 1024 преобразится в long перед сложением

остальных операндов меняется на long. Например:

cval + 1024 + lval;

Из этого правила есть одно исключение: преобразование unsigned int в long происходит только в том случае, если тип long способен вместить весь диапазон значений unsigned int. (Обычно это не так в 32-битных системах, где и long, и int представляются одним машинным словом.) Если же тип long не способен представить весь диапазон unsigned int, оба операнда приводятся к unsigned long.

cvat + fva1 + iva1;

Если у нас нет вещественных операндов , значит, все они представляют собой целые типы. Прежде чем определить тип результата, производится преобразование, называемое приведением к целому: все операнда: с типом меньше, чем int, заменяются на int.

При приведении к целому типы char, signed char, unsigned char и short int преобразуются в int. Тип unsigned short int трансформируется в int, если этот тип достаточен для представления всего диапазона значений unsigned short int (обычно это происходит в системах, отводящих полслова под short и целое слово под int), в противном случае unsigned short int заменяется на unsigned int.

Тип wchar t и перечисления приводятся к наименьшему целому типу, способному представить все их значения. Например, в перечислении

enum status { bad, ok };

значения элементов равны 0 и 1. Оба эти значения могут быть нредставлены типом char, значит char и станет типом внутреннего представления данного перечисления. Приведение к целому преобразует char в int.



int iva1; int *pi = 0;

char *pc = 0;

void *pv;

pv =

pi; правильно: неявное преобразование pv = pc; правильно: неявное преобразование

const int *pci = siva1;

pv = pci; ошибка: pv имеет тип, отчн от const void*;

void* иногда называют универсальным указателем. Например:

const void *pcv = pci; правильно

Однако указатель void* не может быть разыменован непосредственно. Компилятор не знает типа объекта, адресуемого этим указателем. Но это известно программисту, который хочет преобразовать указатель void* в указатель определенного типа. С++ не

#inc1ude <cstring>

int ival = 1024;

void *pv;

int *pi = siva1;

const char *pc = a casting call ;

void mumble() {

pv = pi; правильно: pv получает адрес ival

pc = pv; ошибка: нет стандартного преобразования

char[ str1en( pc )+1 ];

char *pstr = new ch;

strcpy( pstr, pc );

обеспечивает подобного автоматического преобразования:

В случае отсутствия операндов типов unsigned long и long, используется тип unsigned int. Если же нет операндов и этого типа, то к int.

Может быть, данное объяснение преобразований типов несколько смутило вас. Запомните основную идею: арифметическое преобразование типов ставит своей целью сохранить точность при вычислении. Это достигается приведением типов всех операндов к типу, способному вместить любое значение любого из присутствующих в выражении операндов.

4.14.3. Явное преобразование типов

Явное преобразование типов производится при помощи следующих операторов: static cast, dynamic cast, const cast и reinterpret cast. Заметим, что, хотя иногда явное преобразование необходимо, оно служит потенциальным источником ошибок, поскольку подавляет проверку типов, выполняемую компилятором. Давайте сначала посмотрим, зачем нужно такое преобразование.

Указатель на объект любого неконстантного типа может быть присвоен указателю типа void*, который используется в тех случаях, когда действительный тип объекта либо неизвестен, либо может меняться в ходе выполнения программы. Поэтому указатель



void mumble 0 {

правильно: программа по-прежнему содержит ошибку, но теперь она компилируется! Прежде всего нужно проверить явн1е преобразования типов...

pc = static cast< char* >( pv );

char *pstr = new char[ str1en( pc )+1 ];

скорее всего приведет к краху strcpy( pstr, pc );

изменить явно:

Другой причиной использования явного преобразования типов может служить необходимость избежать стандартного преобразования или выполнить вместо него собственное. Например, в следующем выражении ival сначала преобразуется в double,

double dval; int iva1;

потом к нему прибавляется dval, и затем результат снова трансформируется в int.

ival += dval;

Mожно уйти от ненужного преобразования, явно заменив dval на int:

ival += static cast< int >( dval );

Третьей причиной является желание избежать неоднозначных ситуаций, в которых возможно несколько вариантов применения правил преобразования но умолчанию. (Mi рассмотрим этот случай в главе 9, когда будем говорить о перегруженных функциях.)

Синтаксис операции явного преобразования типов таков:

cast-name< type >( expression );

Здесь cast-name - одно из ключевых слов static cast, const cast, dynamic cast или reinterpret cast, а type - тип, к которому приводится выражение expression.

Четыре вида явного преобразования введены для того, чтобы учесть все возможные формы приведения типов. Так const cast служит для трансформации константного типа в неконстантный и подвижного (volatile) - в неподвижный. Например:

Компилятор выдает сообщение об ошибке, так как в данном случае указатель pv содержит адрес целого числа ival, и именно этот адрес пытаются присвоить указателю на строку. Если бы такая программа была допущена до выполнения, то вызов функции strcpy(), которая ожидает на входе строку символов с нулем в конце, скорее всего привел бы к краху, потому что вместо этого strcpy () получает указатель на целое число. Подобные ошибки довольно просто не заметить, именно поэтому С++ запрещает неявное преобразование указателя на void в указатель на другой тип. Однако такой тип можно



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

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