|
Программирование >> Инициализация объектов класса, структура
extern void ff(int); extern void ff(void *); ff( 0xffbc ); вызывается ff(int) будет точно соответствовать ff(int) , хотя литерал 0xffbc записан в виде шестнадцатеричной константы. Программист может заставить компилятор вызвать функцию ff(void *) , если явно выполнит операцию приведения типа: ff( reinterpret cast<void *>(0xffbc) ); вызается ff(void*) Если к фактическому аргументу применяется такое приведение, то он приобретает тин, в который преобразуется. Явные приведения типов помогают в управлении процессом разрешения перегрузки. Например, если при разрешении перегрузки получается неоднозначный результат (фактические аргументы одинаково хорошо соответствуют двум или более устоявшим функциям), то для устранения неоднозначности можно применить явное приведение типа, заставив компилятор выбрать конкретную функцию. 9.3.2. Подробнее о расширении типов Под расширением типа понимается одно из следующих преобразований: фактический аргумент типа char, unsigned char или short расширяется до типа int. Фактический аргумент типа unsigned short расширяется до типа int, если машинный размер int больше, чем размер short, и до типа unsigned int в противном случае; аргумент типа float расширяется до типа double; аргумент перечислимого типа расширяется до первого из следующих типов, который способен представить все значения элементов перечисления: int, unsigned int, long, unsigned long; аргумент типа bool расширяется до типа int. Подобное расширение применяется, когда тип фактического аргумента совпадает с одним из только что перечисленных типов, а формальный параметр относится к extern void manip( int ); int main() { manip( a ); тип char расширяется до int return 0; соответствующему расширенному типу: Символьный литерал имеет тип char. Он расширяется до int. Поскольку расширенный тип соответствует типу формального параметра функции manip() , мы говорим, что ее вызов требует расширения типа аргумента. то вызов extern void print( unsigned int ); extern void print( int ); extern void print( char ); unsigned char uc; Рассмотрим следующий пример: print( uc ); print( int ); для uc требуется только расширение типа Для аппаратной платформы, на которой unsigned char занимает один байт памяти, а int - четыре байта, расширение преобразует unsigned char в int, так как с его помощью можно представить все значения типа unsigned char. Для такой машинной архитектуры из приведенного в примере множества перегруженных функций наилучшее соответствие аргументу типа unsigned char обеспечивает print(int) . Для двух других функций установление соответствия требует стандартного приведения. Следующий пример иллюстрирует расширение фактического аргумента перечислимого enum Stat ( Fail, Pass ); extern void ff( int ); extern void ff( char ); int main() { правильно: элемент перечисления Pass расширяется до типа int ff( Pass ); ff( int ) ff( 0 ); ff( int ) типа: Иногда расширение перечислений преподносит сюрпризы. Компиляторы часто выбирают представление перечисления в зависимости от значений его элементов. Предположим, что в вышеупомянутой архитектуре (один байт для char и четыре байта для int) определено такое перечисление: enum e1 { a1, b1, c1 }; Поскольку есть всего три элемента: a1, b1 и c1 со значениями 0, 1 и 2 соответственно - и поскольку все эти значения можно представить типом char, то компилятор, как правило, и выбирает char для представления типа e1. Рассмотрим, однако, перечисление e2 со следующим множеством элементов: enum e2 { a2, b2, c2=0x80000000 }; Так как одна из констант имеет значение 0x80000000, то компилятор обязан выбрать для представления e2 такой тип, который достаточен для хранения значения 0x80000000, то есть unsigned int. Итак, хотя и e1, и e2 являются перечислениями, их представления различаются. Из-за этого e1 и e2 расширяются до разных типов: #include <string> string format( int ); string format( unsigned int ); int main() { format(al); вызается format( int ) format(a2); вызывается format( unsigned int ) return 0; При первом обращении к format() фактический аргумент расширяется до типа int, так как для представления типа e1 используется char, и, следовательно, вызывается перегруженная функция format(int) . При втором обращении тип фактического аргумента e2 представлен типом unsigned int и аргумент расширяется до unsigned int, из-за чего вызывается перегруженная функция format(unsigned int) . Поэтому следует помнить, что поведение двух перечислений по отношению к процессу разрешения перегрузки может быть различным и зависеть от значений элементов, определяющих, как происходит расширение типа. 9.3.3. Подробнее о стандартном преобразовании Имеется пять видов стандартных преобразований, а именно: 1. преобразования целых типов: приведение от целого типа или перечисления к любому другому целому типу (исключая трансформации, которые выше были отнесены к категории расширения типов); 2. преобразования типов с плавающей точкой: приведение от любого типа с плавающей точкой к любому другому типу с плавающей точкой (исключая трансформации, которые выше были отнесены к категории расширения типов); 3. преобразования между целым типом и типом с плавающей точкой: приведение от любого типа с плавающей точкой к любому целому типу или наоборот; 4. преобразования указателей: приведение целого значения 0 к тину указателя или трансформация указателя любого типа в тип void*; 5. преобразования в тин bool: приведение от любого целого тина, тина с плавающей точкой, перечислимого типа или указательного типа к типу bool. extern void print( void* ); extern void print( double ); int main() { int i; print( i ); соответствует print( double ); i подвергается стандартному преобразованию из int в double print( &i ); соответствует print( void* ); &i подвергается стандартному преобразованию из int* в void* return 0; Вот несколько примеров:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |