
- •Введение. Принципы объектно-ориентированного программирования
- •Глава 1. Классы и объекты
- •1.1. Операция разрешения области видимости ::
- •1.2. Перечислимый тип
- •1.3. Модификатор const
- •1.4. Новый тип данных – ссылка &
- •Inline определение_функции
- •2. Определение класса. Сокрытие информации.
- •3. Объект.
- •4. Конструкторы и деструкторы
- •4.1.Назначение конструктора
- •4.2. Конструктор копирования
- •X::X(X&); // где X – имя класса
- •4.3. Деструктор
- •5. Неявный указатель this
- •6. Перегрузка операций
- •7. Примеры перегрузки некоторых операций
- •7.1. Перегрузка операции [ ]
- •7.2. Перегрузка операции ()
- •7.6. Перегрузка операции (тип)
- •8. Дружественность
- •Istream
- •10. Массивы объектов.
- •11. Функции- и классы-шаблоны
- •11.1 Функции-шаблоны (родовые функции)
- •11.2 Классы-шаблоны
- •12. Член-данные класса – объекты другого класса: агрегированные классы.
- •Глава 2. Наследование. Полиморфизм
- •1. Базовый и порожденный классы
- •2. Конструкторы порожденного класса
- •3. Стандартные преобразования при наследовании
- •4. Множественное наследование. Виртуальный базовый класс
- •4.1. Прямые базовые классы
- •4.2. Виртуальный базовый класс
- •5. Полиморфизм, раннее и позднее связывание, виртуальные функции
- •5.1 Раннее (статическое) и позднее (динамическое) связывание
- •5.2. Определение виртуальной функции
- •5.3. Чистая виртуальная функция и абстрактный класс
- •5.4. Правила определения виртуальных функций
- •5.5. Механизм позднего связывания
- •6. Библиотека fstream – работа с файлами
- •Глава 3. Библиотека стандартных шаблонов (бсш). Контейнеры
- •1. Контейнер. Структура бсш.
- •2. Контейнер Vector – динамический массив
- •Контейнер list – список
- •4. Контейнер Set – множество
- •Содержание
- •Глава 1. Классы и объекты
- •Глава 2. Наследование. Полиморфизм
- •Глава 3. Библиотека стандартных шаблонов (бсш). Контейнеры
1.4. Новый тип данных – ссылка &
Ссылка задает альтернативное имя переменной (псевдоним).
Формат
тип & имя_1 = имя_2;
Ссылка при объявлении всегда должна быть проинициализирована, и в дальнейшем ее изменить нельзя.
Например,
int a, b = 4;
int & x = a;
x = b; // равносильно a = b
x++; // равносильно a++
Если вывести адреса a и x
printf(“%u %u”, &x, &a);
то они будут показывать на одну ячейку.
Сравним ссылку с понятием указателя.
int *y = &a;
Будут справедливы следующие логические выражения
*y = = x // содержимое по адресу, который находится
// в указателе сравнимо с целочисленной переменной
y = = &x // указатель можно сравнить с адресом
// целочисленной переменной
Таким образом, ссылку можно рассматривать как постоянный (константный) указатель, который всегда разадресован, т.е. к нему не нужно применять операцию разадресации *.
Этот тип данных в С++ введен по следующим причинам:
для того чтобы избежать копирования значения фактического аргумента в формальный аргумент функции; особенно это важно для сложных типов данных – структур, классов;
для того чтобы иметь возможность менять значения фактических аргументов (см. ниже пункт 6 б)).
1.5. Функции в С++
а) объявление и определение функций
В языке С++ вызываемая функция должна быть известна выше вызова. Чтобы не следить за этим, все функции можно объявить в начале программы перед всеми определениями и вызовами.
Объявление имеет вид
тип_возв_знач имя_функции (тип_форм_арг1, тип_форм_арг2,...);
Например,
void Prv(int, int*);
int Fs(double);
double Fc(double, double);
char Ps(char*);
Определения этих функций (прототипов) можно поместить теперь где угодно.
б) передача аргументов в функцию
Передача аргументов в функцию может осуществляться 3 способами:
по значению. Значение фактического аргумента присваивается формальному.
При этом значение фактического аргумента никогда не может измениться.
по указателю. Формальному аргументу-указателю передается адрес фактического аргумента. В этом случае значение фактического аргумента может измениться, если применять операции разадресации * и присвоения =.
по ссылке. В этом случае формальный аргумент – это ссылка на фактический, то есть и фактический и формальный аргумент – имя одной и той же ячейки.
Следовательно, при изменении формального аргумента всегда будет меняться и фактический.
Рассмотрим 3 способа передачи аргументов на классическом примере функции обмена значений двух переменных.
void Swap(int x, int y)
{int z;
z = x; x = y; y = z;
}
void main()
{int a = 7, b = 5;
Swap(a, b);
// обмена a и b нет
cout << a << ’,’ << b;
// 7, 5
}
void Swap(int * x, int * y)
{int z;
z = *x; *x = *y; *y = z;
}
void main()
{int a = 7, b = 5;
Swap(&a, &b);
cout << a << ’,’ << b;
// 5, 7
}
void Swap(int &x, int &y)
{int z;
z = x; x = y; y = z;
}
void main()
{ int a = 7, b = 5;
Swap(a, b);
cout << a << ’,’ << b;
// 5, 7
}
в) inline-функции
Обычно определяемая функция компилируется отдельным модулем (подпрограммой). Поэтому обращение к функции и возврат из нее выполняются по определенным правилам (например, сохранение регистров общего назначения (РОН) в стеке при входе в функцию и восстановление их при выходе из нее и др.). Если код функции маленький, то каждое обращение ведет к лишним временным (“накладным”) расходам. Избежать этого можно, если определить функцию со словом inline: