- •Часть 3. Объектно-ориентированное программирование
- •Екатеринбург
- •Введение
- •Классы Описание класса
- •Описание объектов
- •Указатель this
- •Конструкторы
- •Конструктор копирования
- •Конструктор копирования для класса monstr:
- •Статические элементы класса
- •Статические поля
- •Статические методы
- •Дружественные функции и классы Дружественные функции
- •Дружественный класс
- •Деструкторы
- •Перегрузка унарных операций
- •Перегрузка бинарных операций
- •Перегрузка операции присваивания
- •Перегрузка операции приведения типа
- •Наследование Ключи доступа
- •Простое наследование
- •Правила наследования методов
- •Виртуальные методы и механизм позднего связывания
- •Абстрактные классы
- •Обработка исключительных ситуаций
- •Синтаксис исключений
- •Перехват исключений
- •Список исключений
- •Иерархии исключений
- •Библиографический список
- •Оглавление
- •Часть 3. Объектно-ориентированное программирование
- •620002, Екатеринбург, ул.Мира, 19
- •620002, Екатеринбург, ул.Мира, 19
Простое наследование
Простым называется наследование, при котором производный класс имеет одного родителя. Для различных методов класса существуют разные правила наследования – например, конструкторы и операция присваивания в производном классе не наследуются, а деструкторы наследуются.
Пример. Описание класса daemon, производного от класса monstr:
enum color {red, green, blue};
// monstr
class monstr {
//
int health, ammo;
color skin;
char * name;
public:
//
monstr (int he=100, int am=10);
monstr (color sk);
monstr (char *nam);
monstr (monstr &M);
//
~ monstr ( ) {delete [ ] name;}
//
monstr & operator + + ( ) {
+ + health; return *this;
}
monstr operator + + (int) {
monstr M (*this);
health + +; return M;
}
operator int ( )
return health;
}
bool operator > (monstr &M) {
if (health > M.get_heath ( )) return true;
return false;
}
const monstr & operator = (monsr &M) {
if (&M = = this) return *this;
if (name) delete [ ] name;
if (M.name) {
namt = new char [strlen(M.name)+1];
strcpy (name, M.name); }
else name = 0;
health =M.health; ammj=M.ammo; skin =M.skin;
return *this;
}
//
int get_health ( ) const {return health;}
int get_ammo ( ) const { return ammo;}
//
void change_health (int he) {healt=he;}
//
void draw (int x, int y, int scale, int position);
//
monstr: : monstr (int he, int am):
health (he), ammo (am), skin (red), name (0) { }
monstr : : monstr (monstr &M) {
if (M.name) {
name = new char [strlen(M.name)+1];
strcpy (name, M.name;}
else name = 0;
health =M.health; ammo=M.ammo; skin = M.skin;
}
monstr : :monstr (color sk) {
switch (sk) {
case red: health =100; ammo=1`0; skin = red;
name=0; break;
case green: health =100; ammo=20, skin=green;
name=0; break;
case blue: health=100; ammo=40; skin=blue;
name=0; break;
}
}
monstr : : monstr (char * nam) {
name= new char [strlen(nam)+1];
strcpy(name, nam);
health=100; ammo=10; skin=red;
}
void monstr: : draw (int x, int y, int scale, int position)
{/**/}
//
class daemon : public monstr {
int brain;
public:
//
daemon (int br=10) {brain=br;}
daemon (color sk): monstr (sk) {brain =10;}
daemon (char *nam) : monstr (nam) {brain=10;}
daemon (daemon &M): monstr (M) {brain=M.brain;}
//
const daemon &operator = (daemon &M) {
if (&M = =this) return *this;
brain = M.brain;
monstr : : operator =(M);
return *this;
}
//
void think ( );
//
void draw (int x, int y, int scale, int position);
}
//
void daemon : : think ( ) {/* */}
void daemon : : draw (int x, int y, int scale, int position) {/* */}
!!! В классе daemon введено поле brain и метод think, определены собственные конструкторы и операция присваивания, а также переопределен метод draw. Все поля класса monstr, операции (кроме присваивания) и методы get_health, get_ammo и change_health наследуются в классе daemon, а деструктор формируется по умолчанию.
Правила наследования методов
Конструкторы не наследуются, поэтому производный класс должен иметь собственные конструкторы. Порядок вызова конструкторов определяется следующими правилами:
- если в конструкторе производного класса явный вызов конструктора базового класса отсутствует, автоматически вызывается конструктор базового класса по умолчанмию (т.е. тот, который можно вызвать по умолчанию; пример – первый из конструкторов класса daemon);
- для иерархии, состоящей из нескольких уровней, конструкторы базовых классов вызываются, начиная с самого верхнего уровня. После этого выполняются конструкторы тех элементов класса, которые являются объектами, в порядке их объявления в классе, а затем исполняется конструктор класса;
- в случае нескольких базовых классов их конструкторы вызываются в порядке объявления.
Не наследуется операция присваивания, поэтому ее следует также явно определить в производном классе.
Для деструкторов существуют следующие правила наследования:
- деструкторы не наследуются, и если программист не описал в производном классе деструктор, он формируется по умолчанию и вызывает деструкторы всех базовых классов;
- в отличие от конструкторов при написании деструкторов производного класса в нем не требуется явно вызывать деструкторы базовых классов;
- для иерархии классов, состоящей из нескольких уровней, деструкторы вызываются в порядке, строго обратном вызову конструкторов: сначала вызывается деструктор класса, затем деструкторы элементов класса, затем деструктор базового класса.
Поля, унаследованные из класса monstr, недоступны функциям производного класса, поскольку они определены в базовом классе как private. Если функциям, определенным в daemon, требуется работать с этими полями, можно либо описать их в базовом классе как protected, либо обращаться к ним с помощью функций из monstr, либо явно переопределить их в daemon.
В классе daemon описан метод draw, переопределяющий метод с тем же именем в классе monstr. Доступ к переопределяющему методу базового класса для производного класса выполняется через имя, уточненное с помощью операции доступа к области видимости (::).
Задание
Образуйте производный класс от созданного вами класса, который в дополнение к родительским методам может вычислять тригонометрические функции, степенную функцию (степень – вещественное число), экспоненциальную функцию и десятичный логарифм.