Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
68.18 Кб
Скачать

3.1. Модификаторы наследования

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

class Parent {....};

class Child : [модификатор наследования] Parent {....};

Модификатор наследования определяет видимость наследуемых переменных и методов для пользователей и возможных потомков самого класса-потомка. Другими словами, он определяет, какие права доступа к переменным и методам класса-родителя будут переданы классу-потомку. При реализации наследования область видимости принадлежащих классу данных и методов можно определять выбором ключевого слова private (собственный), public (общедоступный) или protected (защищенный), которые могут произвольно чередоваться внутри описания класса.

private описывает закрытые члены класса, доступ к которым имеют только методы-члены этого класса, public предназначен для описания общедоступных элементов, доступ к которым возможен из любого места в программе. Особый интерес представляют элементы, обладающие модификатором доступа protected.

Модификатор protected используется тогда, когда необходимо, чтобы некоторые члены базового класса оставались закрытыми, но были бы доступны для производного класса. Модификатор protected эквивалентен private с единственным исключением: защищенные члены базового класса доступны для членов всех производных классов этого базового класса.

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

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

Базовый класс, производный класс или и тот, и другой могут иметь конструкторы и/или деструкторы. Если и у базового, и у производного классов есть конструкторы и деструкторы, то конструкторы выполняются в порядке наследования, а деструкторы - в обратном порядке. То есть если А - базовый класс, В - производный из А, а С - производный из В (А-В-С ), то при создании объекта класса С вызов конструкторов будет иметь следующий порядок: конструктор А - конструктор В - конструктор С . Вызов деструкторов при разрушении этого объекта произойдет в обратном порядке: деструктор С - деструктор В - деструктор А.

Понять закономерность такого порядка несложно, поскольку базовый класс «не знает» о существовании производного класса, любая инициализация выполняется в нем независимо от производного класса, и, возможно, становится основой для инициализации, выполняемой в производном классе. С другой стороны, поскольку базовый класс лежит в основе производного, вызов деструктора базового класса раньше деструктора производного класса привел бы к преждевременному разрушению производного класса.

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

Однако при необходимости передать аргумент конструктору родительского класса требуется несколько большее усилие. Прежде всего, нужно позаботиться о том, чтобы передать параметры из конструктора производного класса конструктору базового класса. Для этого используется расширенная запись конструктора производного класса.

конструктор_производного_класса (список формальных параметров):

конструктор_базового_класса (список фактических параметров)

{

... // тело конструктора производного класса

}

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

class BaseClass

{

int i;

public:

BaseClass(int ii)

{i=ii;}

~BaseClass()

{cout << ' Работа деструктора базового класса \n';}

};

class DerivedClass: public BaseClass

{

int n;

public:

DerivedClass(int nn, int m): BaseClass (m)

{n=nn;}

~DerivedClass()

{cout << ' Работа деструктора производного класса \n';}

};

main()

{

DerivedClass obj(2,3);

}

Допускается также, что конструктор базового класса может иметь больше параметров, чем конструктор производного класса.

class BaseClass

{

int j, i;

public:

BaseClass(int jj, int ii)

{j=jj; i=ii;}

~BaseClass()

{cout << 'Работа деструктора базового класса \n';}

};

class DerivedClass: public BaseClass

{

int n;

public:

DerivedClass(int nn);

~DerivedClass()

{cout << ' Работа деструктора производного класса \n';}

};

DerivedClass :: DerivedClass(int nn): BaseClass(nn/2, nn%2)

{n=nn;}

main()

{

DerivedClass obj(15);

}

Еще раз обратим внимание на то, что в расширенной форме объявления конструктора производного класса описывается вызов конструктора базового класса.