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

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


#include <list>

применяется. Например, пусть объявлена такая функция:

void print( list<int> & );

В вызове ниже li - это 1-значение, представляющее объект list<int>, передаваемый

list<int> li(20);

int main() {

...

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

rvalue

return 0; функции print() :

Сопоставление li с параметром-ссылкой считается точным соответствием.

Второе преобразование, при котором все же фиксируется точное соответствие, - это преобразование массива в указатель. Как уже отмечалось в разделе 7.3, параметр функции никогда не имеет тип массива, трансформируясь вместо этого в указатель на его первый элемент. Аналогично фактический аргумент типа массива из NT (где N - число элементов в массиве, а T - тип каждого элемента) всегда приводится к типу указателя на T. Такое преобразование типа фактического аргумента и называется преобразованием массива в указатель. Несмотря на это, считается, что фактический аргумент точно

int ai[3];

void putValues(int *);

int main() { ...

putValues(ai); точное соответствие: преобразование массива в указатель

return 0;

соответствует формальному параметру типа указатель на T . Например:

Перед вызовом функции putValues() массив преобразуется в указатель, в результате чего фактический аргумент ai (массив из трех целых) приводится к указателю на int.

Так как аргумент в вызове print(color) передается по значению, то производится преобразование 1-значения в г-значение для извлечения значения color и передачи его в функцию с прототипом print(string) . Однако несмотря на то, что такое приведение имело место, считается, что фактический аргумент color точно соответствует объявлению print(string) .

При вызове функций не всегда требуется применять к аргументам подобное преобразование. Ссылка представляет собой 1-значение; если у функции есть параметр-ссылка, то при вызове функция получает 1-значение. Поэтому к фактическому аргументу, которому соответствует формальный параметр-ссылка, описанное преобразование не



int lexicoCompare( const string &, const string & );

typedef int (*PFI)( const string &, const string & ); void sort( string *, string *, PFI );

string as[10];

int main() {

...

sort( as,

as + sizeof(as)/sizeof(as[0] - 1 ), lexicoCompare точное соответствие

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

return 0;

формальному параметру. Например:

Перед вызовом sort() применяется преобразование функции в указатель, которое приводит аргумент lexicoCompare от типа функция к типу указатель на функцию . Хотя формальным параметром функции является указатель, а фактическим - имя функции и, следовательно, было произведено преобразование функции в указатель, считается, что фактический аргумент точно третьему формальному параметру функции

sort() .

Последнее из перечисленных выше - это преобразование спецификаторов. Оно относится только к указателям и заключается в добавлении спецификаторов const или volatile

int a[5] = { 4454, 7864, 92, 421, 938 }; int *pi = a;

bool is eal( const int * , const int * );

void func( int *parm ) {

точное соответствие между pi и parm: преобразование спецификаторов if ( is eal( pi, parm ) )

...

return 0;

(или обоих) к типу, который адресует данный указатель:

Хотя формальным параметром функции putValues() является указатель и фактический аргумент при вызове преобразован, между ними устанавливается точное соответствие.

При установлении точного соответствия допустимо также преобразование функции в указатель. (Оно упоминалось в разделе 7.9.) Как и параметр-массив, параметр-функция становится указателем на функцию. Фактический аргумент тина функция также автоматически приводится к типу указателя на функцию. Такое преобразование типа фактического аргумента и называется преобразованием функции в указатель. Хотя трансформация производится, считается, что фактический аргумент точно соответствует



extern void takeCI( const int );

int main() { int ii =

takeCI(ii); преобразование спецификаторов не применяется

return 0;

или volatile, а фактический аргумент - нет.

Хотя формальный параметр функции takeCI() имеет тип const int, а вызывается она с аргументом ii типа int, преобразование спецификаторов не производится: есть точное соответствие между фактическим аргументом и формальным параметром.

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

extern void init( int *const ); extern int *pi;

int main() {

...

init(pi); преобразование спецификаторов не применяется

return 0;

const или volatile относятся к этому указателю:

Спецификатор const при формальном параметре функции init() относится к самому указателю, а не к типу, который он адресует. Поэтому компилятор при анализе преобразований, которые должны быть применены к фактическому аргументу, не учитывает этот спецификатор. К аргументу pi не применяется преобразование спецификатора: считается, что этот аргумент и формальный параметр точно соответствуют друг другу.

Первые три из рассмотренных преобразований (1-значения в г-значение, массива в указатель и функции в указатель) часто называют трансформациями l-значений. (В разделе 9.4 мы увидим, что хотя и трансформации 1-значений, и преобразования спецификаторов относятся к категории преобразований, не нарушающих точного соответствия, его степень считается выше в случае, когда необходима лишь первая трансформация. В следующем разделе мы поговорим об этом несколько подробнее.)

Точное соответствие можно установить принудительно, воспользовавшись явным приведением типов. Например, если есть две перегруженные функции:

Перед вызовом функции is equal() фактические аргументы pi и parm преобразуются из типа указатель на int в тип указатель на const int . Эта трансформация заключается в добавлении спецификатора const к адресуемому типу, поэтому относится к категории преобразований спецификаторов. Несмотря на то, что функция ожидает получить два указателя на const int, а фактические аргументы являются указателями на int, считается, что точное соответствие между формальными и фактическими параметрами функции is equal() установлено.

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



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

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