Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Козак Н.В. Лекции Основы создания программ в Си...doc
Скачиваний:
24
Добавлен:
23.09.2019
Размер:
2.24 Mб
Скачать

Доступ к базовым классам

Ключ доступа определяет «внешний» доступ к элементам базового класса через объекты производного. Что касается доступа самого производного класса к элементам базового класса, то ключ доступа на него не влияет. Для производного класса доступны разделы protected и public базового класса; раздел private строго недоступен вне области действия базового класса.

Для доступа к элементам базового класса через производный можно сформулировать такое правило: права доступа, определяемые для них базовым классом, остаются неизменными, если они такие же или строже, чем специфицировано ключом доступа. В противном случае права доступа определяются ключом в определении производного класса.

Например, при наследовании с ключом public права доступа к элементам базового класса остаются неизменными; при закрытом наследовании (ключ private) все элементы базового класса будут недоступны за пределами производного класса.

При закрытом наследовании не допустимы преобразования экземпляра производного класса к базовому типу.

Простое наследование

При простом наследовании производный класс порождается всего одним базовым классом.

#include <stdio.h>

#include <string.h>

class Time // Базовый класс - время.

{

int _hr, _min;

public:

Time(int h=12, int m=0): _hr(h), _min(m)

{}

void setTime (int h, int m) { _hr = h; _min = m; }

void show();

};

void Time::show ()

{

printf("%02d:%02d", hr, min);

}

class Alarm: public Time // Класс сообщений таймера.

{

char *msg;

public:

Alarm(char*);

~Alarm() { delete[] msg; }

void setMsg(char*);

void show(); // Переопределяет Time::show().

};

Alarm::Alarm(char *str);

{

msg = new char[strlen(str) + 1];

strcpy(msg, str);

}

void Alarm: :setMsg (char *str)

{

delete[] msg;

msg = new char[strlen (str) + 1];

strcpy(msg, str);

}

void Alarm::show()

{

Time::show(); // Вызов базовой show().

printf(": %s\n", msg);

}

int main()

{

Alarm a = "Test Alarm!!!"; // Время по умолчанию 12:00.

a.show();

a.setTime(7, 40); // Функция базового класса.

a.show ();

a.setMsg("It' s time!"); // Функция производного класса.

a.show ();

return 0;

}

Конструкторы, деструкторы и наследование

Конструкторы не наследуются. Если в базовом классе имеется конструктор с некоторыми параметрами, он не будет вызываться автоматически, если вы попробуете создать объект производного класса с такими параметрами. Для этого нужно написать конструктор производного класса, в котором конструктор базового класса будет вызываться через посредство списка инициализации.

Если в списке инициализации конструктора отсутствует вызов какого бы то ни было конструктора базового класса, компилятор все равно вызовет для последнего конструктор по умолчанию, т.е. конструктор без параметров.

Однако базовый конструктор можно вызвать и явно, через список инициализации. Класс из предыдущего параграфа нужно модифицировать примерно так:

class Alarm: public Time // Класс сообщений таймера.

{

char *_msg;

public:

Alarm(char*);

Alarm(char*, int, int); // Новый конструктор.

~Alarm() { delete[] _msg; }

void setMsg(char*);

void show(); // Переопределяет Time::show().

};

//. . .

Alarm::Alarm(char *str, int h, int m): Time(h, m)

{

_msg = new char[strlen(str) + 1];

strcpy(_msg, str);

}

С другой стороны, деструкторы базовых классов никогда явно не вызываются Компилятор автоматически генерирует вызовы всех необходимых деструкторов.