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

1 ... 143 144 145 [ 146 ] 147 148 149 ... 395


unsigned int a;

print( a ); соответствует print( char ); print( a ); соответствует print( const char* );

то каждый из следующих трех вызовов дает точное соответствие:

print( a ); соответствует print( unsigned int );

соответствие с преобразованием типа. Тип фактического аргумента не

void ff( char );

соответствует типу формального параметра, но может быть преобразован в него:

ff( 0 ); аргумент типа int приводится к типу char

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

функции print() объявлены так же, как и выше

*ip;

class SmallInt { /* ... */ }; SmallInt si;

print( ip ); ошибка: нет соответствия

вызовов функции print () соответствия нет:

print( si ); ошибка: нет соответствия

Для установления точного соответствия тип фактического аргумента необязательно должен совпадать с типом формального параметра. К аргументу могут быть применены некоторые тривиальные преобразования, а именно:

преобразование l-значения в г-значение;

преобразование массива в указатель;

преобразование функции в указатель;

преобразования спецификаторов. (Подробнее они рассмотрены ниже.)

Категория соответствия с преобразованием типа является наиболее сложной. Необходимо рассмотреть несколько видов такого приведения: расширение типов (promotions), стандартные преобразования и определенные пользователем преобразования. (Расширения типов и стандартные преобразования изучаются в этой главе. Онределенн1е пользователем преобразования будут нредставлены позднее, после детального рассмотрения классов; они выполняются конвертером, функцией-членом, которая позволяет определить в классе собственн1й набор стандартных трансформаций. В главе 15 мы познакомимся с такими конвертерами и с тем, как они влияют на разрешение перегрузки функций.)



int max( int, int );

double max( double, double );

int i1;

void calc( double d1 ) {

max( 56, i1 ); точно соответствует max( int, int ); max( d1, 66.9 ); точно соответствует max( double, double );

объявлений:

Перечислимый тип точно соответствует только определенным в нем элементам

= 128; VIRTUAL = 129; };

Tokens

enum Tokens { INLINE = : Tokens curTok = INLINE;

enum Stat { Fail, Pass };

extern void ff( Tokens ); extern void ff( Stat );

extern void ff( int );

int main() {

ff( Pass ); точно соответствует ff( Stat )

ff( 0 ); точно соответствует ff( int )

ff( curTok ); точно соответствует ff( Tokens )

...

перечисления, а также объектам, которые объявлены как принадлежащие к этому типу:

Выше уже упоминалось, что фактический аргумент может точно соответствовать формальному параметру, даже если для приведения их типов необходимо некоторое тривиальное преобразование, первое из которых - преобразование 1-значения в г-значение. Под 1-значением понимается объект, удовлетворяющий следующим условиям:

можно получить адрес объекта;

можно получить значение объекта;

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

9.3.1. Подробнее о точном соответствии

Самый простой случай возникает тогда, когда типы фактических аргументов совпадают с типами формальных параметров. Например, есть две показанные ниже перегруженные функции max() . Тогда каждый из вызовов max() точно соответствует одному из



int calc( int );

int main() {

int lval, res;

lval = 5; lvalue: lval; rvalue: 5

res = calc( lval );

lvalue: res

return 0;

rvalue: временн объект для хранения значения, возвращаемого функцией calc()

которое нельзя модифицировать. Вот простой пример:

В нервом операторе присваивания неременная lval - это l-значение, а литерал 5 - г-значение. Во втором операторе присваивания res - это l-значение, а временный объект, в котором хранится результат, возвращаемый функцией calc() , - это г-значение.

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

int obj1; int obj 2;

int main()

...

int local = objl + obj2; return 0;

выражение, представляющее собой l-значение:

Здесь objl и obj2 - это l-значения. Однако для выполнения сложения в функции miain() из неременн1х objl и obj2 извлекаются их значения. Действие, состоящее в извлечении значения объекта, представленного выражением вида l-значение, называется преобразованием l-значения в г-значение.

Когда функция ожидает аргумент, переданный по значению, то в случае, если аргумент

#include <string>

string color( purple );

void print( string );

int main() {

print( color ); точное соответствие: преобразование lvalue в rvalue

return 0;

является l-значением, выполняется его преобразование в г-значение:

это значение легко модифицировать (если только в объявлении объекта нет спецификатора const).

Напротив, г-значение - это выражение, значение которого вычисляется, или выражение, обозначающее временный объект, для которого нельзя получить адрес и значение



1 ... 143 144 145 [ 146 ] 147 148 149 ... 395

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