книга (И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++), страница 10
Описание файла
Файл "книга" внутри архива находится в папке "И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++". PDF-файл из архива "И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++", который расположен в категории "". Всё это находится в предмете "практикум (прикладное программное обеспечение и системы программирования)" из 4 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 10 страницы из PDF
. . f (1, 1) . . .} // вызов первой реализацииf(x, int)Пример:class x{. . .public:x(int i1){. . . }. . .};void f (x x1, int i1 ) {. . .}void f (int i1, x x1 ) {. . .}void g () {. . . f(1, 1) . . .}// ошибка: пересечение// множеств — пусто.8.4. Алгоритм поиска оптимальноотождествляемой функциидля одного параметраЕсли функция имеет один параметр, то выполняется следующая последовательность шагов для поиска оптимально отождествляемой функции.Такая же последовательность шагов выполняется для каждого параметра функции с несколькими параметрами на втором этапе ранее описанного алгоритма поиска оптимально отождествляемой функциис несколькими параметрами.1. Точное отождествление.2.
Отождествление с помощью расширений.3. Отождествление с помощью стандартных преобразований.4. Отождествление с помощью преобразований пользователя.5. Отождествление по «…».Данные шаги определяют приоритет метода отождествления параметра.в рамках каждого шага разные виды преобразований являются равно приоритетными.8.4.1 Точное отождествлениеРазличают следующие виды точного отождествления:— Точное совпадение— Совпадение с точностью до typedef— Тривиальные преобразования: T[] ↔ T*57Статический полиморфизмT ↔ T&T → const TПример:voidvoidvoidvoidfffg(float);(double);(int);() { .
. . f(1.0F); . . . f(1.0); . . . f(1);}8.4.2 Отождествление с помощьюрасширений8.4.2.1. Целочисленные расширенияРазличают следующие виды целочисленного расширения:ПримечаниеЕсли фактический параметр невозможно преобразовать к типу signed int безпотери информации, то осуществляется его преобразование к типу unsignedint. Дело в том, что на три основных целочисленных типа — short, int и long, всамых распространенных компиляторах отводится два основных размера — 2 и4 байта. При этом, в разных компиляторах одинаковый размер имеют разныецелочисленные типы.
Так, в компиляторе Borland С++ 3.1 типы short и intимеют размер 2 байта, а long — 4 байта. в компиляторах Borland С++ 5.02 иMicrosoft Visual C++ 6.0 тип short имеет размер 2 байта, а типы int и long —4 байта. Поэтому, если типы short и int имеют одинаковый размер, то преобразование unsigned short → signed int — невозможно.8.4.2.2.
Расширения с плавающей точкойРасширение с плавающей точкой допускает следующее преобразование:float → double8.4.3 Отождествление с помощьюстандартных преобразований8.4.3.1. Остальные стандартные целочисленныеи вещественные преобразованияПример:#include <iostream>58Статический полиморфизмusing namespace std;void f ( char c ){int i;union U{char c1;unsigned b:8;};U u1;u1.c1 = c;cout << u1.b << '\n';i = c;cout << i << '\n';}int main(){f (-1);return 0;}ПримечаниеПри этом тип char — целочисленное значение размером в 1 байт.В выходной поток будет выдано:255 ////-1 ////8-битное представление числа -1,преобразованное в беззнаковое целоерасширенный до целого дополнительный код,представляющий -18.4.3.2. Преобразование указателейКонстанта 0 при преобразовании параметров рассматривается не только какчисло, но и как нулевой указатель.
Нулевой указатель может быть преобразован в любой указатель. Любой указатель может быть преобразован в такназываемый обобщенный (свободный) указатель void*. При этом обратноепреобразование должно выполняться явно.Пример:int main(){int i;void* p;int *ip = &i;////////int* ip2;//*ip = 15;////p = ip;////ip2 = (int*)p; //Обобщенный указательУказатель на int,инициализируемый адресомцелочисленной переменнойУказатель на intРазыменование указателя наintДопустимое неявное преобразованиеуказателяЯвно заданное преобразование59Статический полиморфизм// указателя...return 0;}В связи с тем, что тип char*, используемый для работы с динамическиразмещаемыми строками, является указателем, то при наличии перегруженных функций с прототипами:int f ( char* c1 );int f ( double d1 );вызов i = f (0); будет неоднозначным, так как при отождествлениис помощью стандартных преобразований следующие преобразования равноправны:0 -> double (int -> double)0 -> char* (пустой указатель -> указатель на char)Указатель на объект производного класса может быть преобразованв указатель на объект базового класса.
О наследовании классов будет подробно рассказано далее.Пример:class X{int x1;public:X():x1(0) {}};class Y: public X{int y1;public:Y(): y1(0) {}};void f(X * x2) {}int main(){Y * y2;f(y2); // фактический параметр — указатель на объект// производного класса, а формальный параметр// указатель на объект базового классаreturn 0;}Примечание 1Через указатель на объект базового класса доступны только члены производного класса, унаследованные от базового класса. Это связано с тем, что,как было отмечено, указатели являются типизированными, то есть, в указателехранится не только адрес объекта, но и информация о структуре объекта.60Статический полиморфизмПримечание 2Как будет описано далее, неявное преобразование указателей возможнотолько при открытом (public) — наследовании.8.4.4 Преобразования пользователя8.4.4.1. Конструктор преобразованияКонструктор преобразования может быть использован в качестве неявногопреобразования пользователя только в том случае, если он объявлен безключевого слова explicit.8.4.4.2.
Функция преобразования (операция преобразования)Функция преобразования — это метод класса с прототипом:operator тип();Здесь тип — тип возвращаемого значения (встроенного или пользовательского).Тело данной функции определяет возвращаемое значение. Тело функции должно содержать оператор return, возвращающее данное значение. Приэтом возвращаемое значение преобразуется к указанному типу. Если типявляется пользовательским, то создается временный объект данного типа.При этом вызывается конструктор преобразования, определенный в этомклассе. Возвращаемое функцией значение будет входным параметром дляэтого конструктора.Функция преобразования выполняет действие, обратное действиюконструктора преобразования: если конструктор преобразования создаетобъект типа описываемого класса на основе объекта другого типа, то функция преобразования возвращает объект другого типа на основе объекта(внутренней информации, хранящейся в объекте) описываемого класса.Сходством функции преобразования и конструктора преобразованияявляется то, что у функции преобразования так же, как и у конструкторапреобразования нет типа возвращаемого значения.
Тип возвращаемого значения у функции преобразования определяется типом, указанным послеключевого слова operator.Кроме функции преобразования ключевое слово operator используетсятакже при перегрузке операций, о чем уже было рассказано.При использовании преобразования пользователя строятся все возможные цепочки преобразований параметра, которые позволяют применитьодну из реализаций перегруженной функции.
При этом выбирается та реализация, для которой в цепочке преобразований шаг преобразованияс минимальным приоритетом имеет максимальный приоритет по сравнениюс другими цепочками. Так, если в одной цепочке преобразований шагомс минимальным приоритетом будет шаг 4 (преобразование пользователя),а в другой цепочке — шаг 3 (стандартные преобразования), то будет выбрана61Статический полиморфизмреализация функции, для которой цепочка преобразований параметра содержит шаг 3.Пример:#include <iostream>using namespace std;class S{long ss1;public:S ():ss1(0){}S ( long p ): ss1 (p){cout << "constructor S -> ";}operator int(){cout << "S.operator int() -> ";return ss1;}};void f ( long p ){cout << "f(long)" << '\n';}void f ( char* p ){cout << "f(char*)" << '\n';}void g ( S p ){cout << "g(S)" << '\n';}void g ( char* p ){cout << "g(char*)" << '\n';}void ex ( S& a ){f(a);g(1);g(0);}int main(){S s1;ex(s1);return 0;}Последовательности преобразований параметров при вызове функций fи g в функции ex():1.
f (a):s.operator int() — шаг 4. Преобразование пользователяint −> long — шаг 3. Стандартное преобразование f (long)62Статический полиморфизм2. g(1):int −> long — шаг 2. Расширение (целочисленное)s.constructor (long): шаг 4 — Преобразование пользователя g(s)3. g(0): 0 −> char* — шаг 3. Стандартные преобразования (преобразования указателей — константа 0 преобразуется в указатель)g(char*)Замечание 1Пользовательские преобразования применимы неявно только в том случае,если они однозначны.class B{int i1;public:B ( int p ): i1 (p) {}operator int() { return i1; }B operator+ ( const B & pb ){B tmp(0);tmp.i1 = i1 + pb.i1;return tmp;}};int main(){B x (0);x = x + 1; // неоднозначность: возможно// x.operator int() + 1 либо// x.operator+ ( B(1) )return 0;}63Статический полиморфизмЗамечание 2Допустимо не более одного пользовательского преобразования для одногопараметра.class X{int x1;public:operator int(){return x1;}X(int px):x1(px){}};class Y{int y1;public:operator X(){X tmp (y1);return tmp;}Y() : y1 (0) {}};int main(){Y a;int b;b = a;// ошибка: требуется// a.operator X().operator int ()return 0;}8.4.5 Отождествление по «…»Использование символов «…» в конце списка формальных параметровв описании функции с переменным числом параметров для обозначения оставшихся неявных параметров было описано ранее.Пример:#include <iostream>using namespace std;class X{double x1;public:X ( double px ): x1 (px) {}};void f(int i1, X x2){cout << "f(int, X)" << '\n';}void f(int i1, ...){cout << "f(int, ...)" << '\n';}int main(){f(1,1);f(1,"Test");64Статический полиморфизмreturn 0;}Использование символов «…» может привести к неоднозначности.Например:void f ( int i1 );void f ( int i1, .