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