ЯП_Си++_03_Наследование
.pdf3. Наследование
Базовый класс существующий класс
Отношение «ЯВЛЯЕТСЯ»
Производный класс новый класс
|
|
|
3.1. Параметры доступа |
|
|
По умолчанию |
Спецификатор (статус) доступа |
||||
|
|
|
|
|
|
|
Элементы базового |
|
В производном |
Для клиентов |
|
|
класса |
|
|
классе |
классов |
|
private-элементы |
|
недоступны |
недоступны |
|
|
protected-элементы |
|
доступны |
недоступны |
|
|
public-элементы |
|
|
доступны |
доступны |
1
Ключ доступа
class имя : [private | protected | public] базовый_класс{
}; |
тело класса |
По умолчанию |
|
private – закрытое наследование protected – защищенное наследование public – открытое наследование
Статус доступа |
private- |
|
|
protected - |
public - |
элементов |
наследование |
|
|
наследование |
наследование |
базового класса |
Статус доступа элементов производного класса |
||||
|
|
|
|
|
private |
private |
private |
|
|
private |
|
protected |
private |
|
|
protected |
protected |
public |
private |
|
|
protected |
public |
|
|
2 |
|
|
3.2. Простое наследование (один базовый класс)
Конструкторы
//------------------time.h-------------------
//производный класс от базового класса Time class TimeDate: public Time{
private: int day;
int month; int year;
public: //конструкторы
TimeDate(int = 1, int = 1, int = 1); TimeDate(int, int, int, int, int, int, char *); TimeDate(const TimeDate &);
//операции
TimeDate& operator = (const TimeDate &); //прочие методы
void printTime();
3
}; |
time.cpp |
|
|
//---------------- |
|
||
//---------------- |
конструкторы----------------- |
Явный вызов конструктора |
|
Конструктор по умолчанию |
|||
базового класса отсутствует |
TimeDate::TimeDate(int d, int m, int y){ day = d; month = m; year = y;
}
//автоматически вызывается конструктор по умолчанию //базового класса
Конструктор базового класса требует указания параметров
TimeDate::TimeDate(int h, int m, int s, int d, int mm, int y, char *str): Time(h,m,s,str){
day = d; month = mm; year = y;
}
Конструктор базового класса явно 4 вызван в списке инициализации
Конструктор копирования |
Конструктор копирования базового класса |
|
вызывается в списке инициализации |
TimeDate::TimeDate(const TimeDate &td): Time(td) { day = td.day; month = td.month; year = td.year;
}
Конструктор копирования класса Time вызван с параметром типа TimeDate&, а не Time&
1.Конструкторы не наследуются → производный класс должен иметь собственные конструкторы.
2.В производном классе явно не вызывается конструктор базового класса → автоматически вызывается конструктор по умолчанию базового класса.
3.Конструктор базового класса требует указания параметров → его надо вызвать явно в списке инициализации.
5
|
Операция присваивания |
//------------- |
операция присваивания------------------- |
TimeDate &TimeDate::operator = (const TimeDate &td){ //проверка на самоприсваивание
if (&td == this) return *this;//сравнение адресов
Time::operator = (td);
//явный вызов функции-операции из базового класса
day = td.day; month = td.month; year = td.year;
return *this; |
|
||
} |
|
|
|
1. |
Сокращение объема кода. |
Можно интерпретировать как |
|
имя функции-операции |
|||
2. |
Упрощение модификации. |
||
|
3.Меньше ошибок.
1.Операция присваивания не наследуются → производный класс должен иметь собственную операцию присваивания.
6
Деструкторы
Базовый класс |
Конструкторы |
Деструкторы |
|
|
|
Производный класс
Порядок вызовов конструкторов / деструкторов
1.Деструктор не наследуются → если необходимо (есть поля-указатели и т.п.) производный класс должен иметь собственный явно написанный деструктор.
2.Если деструктор производного класса не написан явно, он создается автоматически.
3.В деструкторе производного класса (как написанного явно, так и созданного автоматически) деструктор базового класса вызывается автоматически.
7
Прочие методы
В классе TimeDate описан метод printTime, который переопределяет метод с тем же именем в классе Time.
↓↓
Производный класс может не только дополнять, но и корректировать поведение базового класса!
//------------------прочие методы---------------------------
void TimeDate::printTime(){
printf("%2.2i:%2.2i:%2.2i - %2.2i.%2.2i.%4.4i - %s\n", hour,minute,second,day,month,year,stime);
//если в классе Time private заменить на protected, то //можно получить доступ к полям hour,minute,second,stime
//можно требуемые поля переопределить в TimeDate //public: Time::hour;
}
8
3.3. Виртуальные методы
Time *pt;//указатель на объект |
Time t;//объект |
Эффективнее – указатель на базовый класс можно «связать» с объектом любого производного класса!
//описание указателя на базовый класс
Time *pt;
//указатель ссылается на объект производного класса pt = new TimeDate();
9
//описание указателя на базовый класс
Time *pt;
//указатель ссылается на объект производного класса pt = new TimeDate();
//будет вызван метод класса Time pt->printTime();
тип указателя фактический тип объекта
Раннее (статическое) связывание – на этапе компиляции
Что делать, чтобы вызвать метод класса TimeDate?
1. Явное преобразование типа указателя – не всегда возможно
((TimeDate*) pt)->printTime();
2. Позднее (динамическое) связывании – на этапе выполнения Виртуальные методы.
virtual void printTime();
10
Вызов методов происходит в соответствии с типом объекта