22 Доступ к базовым и производным классам.
При объявлении производного класса Bl, B2 ... в разделяемом запятой базовом-списке:
ключ-класса D:базовый-список
{<список-компонентов>}
D наследует все компоненты базовых классов. (Переопределенные
компоненты базовых классов наследуются, и при необходимости доступ к ним
возможен при помощи переопределений области действия). D может использовать
только компоненты базовых классов с атрибутами public и protected. Однако, что будут представлять
собой атрибуты доступа унаследованных элементов с точки зрения D? D может
понадобиться использовать public
элемент базового класса, но при этом сделать его private для внешних функций.
Решение здесь состоит в том, чтобы использовать в базовом-списке спецификаторы доступа.
Поскольку сам базовый класс может являться производным классом, то вопрос об атрибуте доступа решается рекурсивно: необходимо отслеживать его до тех пор пока не достигнут "самый" базовый класс, породивший все остальные.
При объявлении D можно задать спецификатор доступа public или private перед классами в базовом-спнске
class D: public
B1, private В2, …{ ... }
Задать в базовом-сппске protected нельзя. Объединения не могут содержать базовых классов и не могут сами быть использованы в качестве базовых классов. Эти модификаторы не изменяют атрибутов доступа базовых элементов с точки зрения базового класса, хотя и могут изменить атрибуты доступа базовых элементов с точки зрения производных классов. Умолчанием является private, если D — объявление класса class, и public, если D — объявление структуры struct.
Производный класс наследует атрибуты доступа базового класса следующим образом:
Базовый класс public:
элементы public базового класса становятся элементами public производного класса. Элементы protected базового класса становятся элементами protected производного класса. Элементы private базового класса остаются для базового класса private.
Базовый класс private:
И public,
и protected элементы
базового private класса становятся private элементами производного класса.
Элементы private
базового класса остаются для базового класса private.
В обоих случаях элементы private базового класса были и остаются недоступными для методов производного класса, пока в описании базового класса не будут явно заданы объявления friend, гарантирующие доступ. Например:
class Х :
А
{ // умолчание для класса -
// private A
…
}
/* класс Х является производным от класса А */
class Y : В, public С { // переопределяет
// умолчание для С
…
}
/* класс Y является производным (множественное наследование) от В и С. По умолчанию - private В */
struct S : D { // умолчание для struct - public D
/* struct S - производная от D */
…
}
struct Т : private D, Е { // переопределяет
// умолчание для D
// Е по умолчанию
// pub1iс
…
}
/* struct Т является производной (множественное наследование) от D и Т. По умолчанию - public E */
Действие спецификаторов доступа в базовом списке можно скорректировать при помощи уточненного-имени в объявлениях public или protected для производного класса, например:
class B
{
int a; // по умолчанию private
public:
int d,c;
int Bfunc (void);
};
class X:
private B { // теперь в X a, d, c, и Bfunc -
private
int d; // по умолчанию private. ПРИМЕЧАНИЕ: а в Х недоступна
public:
B::c; // с была private; теперь она public
int d;
int Xfunc(void); //внешняя по отношению к В и Х
Функция Efunc может использовать только имена с атрибутом public, например с, е и Xfunc.
Функция Xfunc в Х является производной от private В, поэтому она имеет доступ к:
"скоррсктированной-к-типу-public" с,
"private-относительно-Х" компонентам В:b и Bfunc;
"собственным private и public" компонентам X: d, e и Xfunc.
Однако Xfunc не имеет доступа к "private - относительно - В" компоненту а.