- •А. В. Кибардин
- •Оглавление
- •Введение
- •Классы Описание класса
- •Описание объектов
- •Указательthis
- •Конструкторы
- •Конструктор копирования
- •Конструктор копирования для класса monstr:
- •Статические элементы класса
- •Статические поля
- •Статические методы
- •Дружественные функции и классы Дружественные функции
- •Дружественный класс
- •Деструкторы
- •Перегрузка унарных операций
- •Перегрузка бинарных операций
- •Перегрузка операции присваивания
- •Перегрузка операции приведения типа
- •Наследование Ключи доступа
- •Простое наследование
- •Правила наследования методов
- •Виртуальные методы и механизм позднего связывания
- •Абстрактные классы
- •Обработка исключительных ситуаций
- •Синтаксис исключений
- •Перехват исключений
- •Список исключений
- •Иерархии исключений
- •Стандартная библиотека
- •Потоковые классы
- •Стандартные потоки
- •Форматирование данных
- •Флаги и форматирующие методы
- •Манипуляторы
- •Методы обмена с потоком
- •Ошибки потоков
- •Файловые потоки
- •Строковые потоки
- •Конструкторы и присваивание строк
- •Операции
- •Функции Присваивание и добавление частей строк
- •Преобразование строк
- •Поиск подстрок
- •Сравнение частей строк
- •Получение характеристик строк
- •Контейнерные классы
- •Последовательные контейнеры
- •Векторы
- •Двусторонние очереди
- •Ассоциативные контейнеры
- •Словари
- •Словари с дубликатами (multimap)
- •Приложение 1. Шаблоны функций
- •Приложение 2. Шаблоны классов
- •Библиографический список
- •В трех частях
Описание объектов
Конкретные переменные типа «класс» называются экземплярами класса или объектами.
Пример
monstr Vasia; // объект с параметрами по умолчанию
monstr Super(200,300); // объект с явной инициализацией
monstr *beavis = new monstr(10); // динамический объект
// второй параметр задается по умолчанию
monstr & butthead = Vasia; // ссылка на объект
Доступ к элементам объекта аналогичен доступу к полям структуры. Для этого используется операция . (точка) при обращении к элементу через имя объекта и операция -> при обращении через указатель:
int n = Vasia.get_ammo( );
stado [5].draw;
cout << beavis ->get_ammo( );
Обратиться таким образом можно только к элементам со спецификатором public. Получить или изменить значения элементов со спецификатором private можно только через обращение к соответствующим методам.
Можно создать константный объект, значения полей которого изменять запрещается. К нему должны применяться только константные методы:
class monstr {
…
int get_health ( ) const {return health;}
};
const monstr Dead (0,0); //
cout << Dead.get_health ( );
Указательthis
Каждый объект содержит свой экземпляр полей класса. Методы класса находятся в памяти в единственном экземпляре и используются всеми объектами совместно, поэтому необходимо обеспечить работу методов с полями именно того объекта, для которого они вызваны. Это обеспечивается передачей в функцию скрытого параметра this, в котором хранится константный указатель на вызвавший функцию объект.
Указатель this неявно используется внутри метода для ссылок на элементы объекта. В явном виде этот указатель применяется в основном для возвращения из метода указателя (return this;) или ссылки (return *this;) на вызвавший объект.
Добавим в класс monstr новый метод, возвращающий ссылку на наиболее сильного (поле health) из двух монстров, один из которых вызывает метод, а другой передается ему в качестве параметра (метод следует поместить в секцию public описания класса):
monstr & the_best (monstr &M) {
if (health >M.get_health ( )) return *this;
return M;
}
…
monstr Vasia (50), Super (200);
monstr Best = Vasia.the_best (Super); // новый объект
// Best инициализируется значениями полей Super
Указатель this можно применять также для идентификации поля класса в том случае, когда его имя совпадает с именем формального параметра. Другой способ – использовать операцию доступа к области видимости (::):
void cure (int health, int ammo) {
this -> health +=health; // используется this
monstr :: ammo +=ammo; // использование ::
}
Конструкторы
Конструктор предназначен для инициализации объекта и вызывается автоматически при его создании. Его свойства:
– конструктор не возвращает значение даже типа void. Нельзя получить указатель на конструктор;
– класс может иметь несколько конструкторов с разными параметрами для разных видов инициализации (при этом используется механизм перегрузки);
– конструктор, вызываемый без параметров, называется конструктором по умолчанию;
– параметры конструктора могут иметь любой тип, кроме типа этого же класса. Можно задавать значения параметров по умолчанию. Их содержит только один из конструкторов;
– если программист не указал ни одного конструктора, компилятор создаст его автоматически;
– конструкторы не наследуются;
– конструкторы нельзя описывать с модификаторами const, virtual и static;
конструкторы глобальных объектов создаются, как только становится активной их область действия;
– конструктор вызывается, если в программе встретилась какая-либо из следующих синтаксических конструкций:
имя_класса имя_объекта [(список параметров)];
// список параметров не должен быть пустым
имя_класса (список параметров);
// создается объект без имени
имя_класса имя_объекта = выражение;
// создается объект без имени и копируется
Примеры
monstr Super (200, 300), Vasia (50), Z;
monstr X = monstr (1000);
monstr Y = 500;
В первом операторе создаются три объекта.
Во втором операторе создается безымянный объект со значением параметра health = 1000; выделяется память под объект X, в которую копируется безымянный объект.
В третьем операторе создается безымянный объект со значением параметра health= 500; выделяется память под объект Y, в которую копируется безымянный объект. Такая форма создания объекта возможна в том случае, если для инициализации объекта допускается задать один параметр.
Пример. Усовершенствованный класс monstr с несколькими конструкторами:
Enum color {red, green, blue}; //
class monstr {
int health, ammo;
color skin;
char *name;
public
monstr (int he =100, int am = 10);
monstr (color, sk);
monstr (char *nam);
int get_health ( ) {return health;}
int get_ammo ( ) {return ammo;}
…
};
//---------------------------------------------
monstr :: monstr (int he, int am) {
health = he; ammo = am; skin = red; name = 0;
}
//----------------------------------------------
monstr :: monstr (color sk) {
switch (sk) {
case red : health = 100; ammo = 10; skin = red; name = 0;
break;
case green : health = 100; ammo = 20; skin = red; name = 0;
break;
case blue : health = 100; ammo = 40; skin = red; name = 0;
break;
}
}
//------------------------------------------------
monstr :: monstr (char *nam) {
name = new char [strlen(nam)+1];
strcpy (name, nam);
health = 100; ammo = 10; skin = red;
}
…
//-------------------------------------------------
monstr *m = new monstr (“Ork”);
monstr Green (green);
Первый из приведенных выше конструкторов является конструктором по умолчанию, поскольку его можно вызвать без параметров. Объекты класса monstr теперь можно инициализировать разными способами, требуемый конструктор будет вызван в зависимости от списка значений в скобках. При задании нескольких конструкторов следует соблюдать те же правила, что и при перегрузке функций.
!!! Перегружать можно не только конструкторы, но и другие методы класса.
Еще один способ инициализации полей в конструкторе – с помощью списка инициализаторов, расположенных после двоеточия между заголовком и телом конструктора:
Monstr : : monstr (int he, int am) :
health (he), ammo (am), skin (sk), name (0) {};
Поля перечисляются через запятую. Для каждого поля в скобках указывается инициализирующее значение, которое может быть выражением. Таким образом инициализируются поля-константы, поля-ссылки и поля-объекты. В последнем случае будет вызван конструктор, соответствующий указанным в скобках параметрам.
Задание
Добавьте в разработанный вами класс-калькулятор конструктор, инициализирующий объект.