Спецификатор доступа при наследовании базового класса
От того, с каким спецификатором доступа объявляется наследование базового класса, зависит статус доступа к членам производного класса. Общая форма наследования классов имеет следующий вид:
class имя_класса: доступ имя_класса
{
};
Здесь доступ определяет, каким способом наследуется базовый класс. Спецификатор доступ может принимать три значения — private, public и protected. В случае, если спецификатор доступ опущен, то по умолчанию подразумевается на его месте спецификатор public. Если спецификатор доступ принимает значение public, то все публичные и защищенные члены базового класса становятся соответственно публичными и защищенными членами производного класса. Если спецификатор доступ имеет значение private, то все публичные и защищенные члены базового класса становятся частными членами производного класса. Если спецификатор доступ принимает значение protected, то все публичные и защищенные члены базового класса становятся защищенными членами производного класса. Для того чтобы усвоить все эти преобразования, рассмотрим пример:
#include <iostream.h>
class X
{
protected:
int i, j;
public:
void get_ij()
{
cout << "Enter two numbers: ";
cin >> i >> j;
}
void put_ij() { cout << i << " " << j << "\n";}
};
class Y: public X
{
int k;
public:
int get_k() { return k; }
void make_k() { k = i*j; }
};
class Z: public Y
{
public:
void f();
};
void z::f()
{
i = 2; //нормально
j = 3; //нормально
}
int main()
{
Y v1;
Z v2;
v1.get_ij();
v1.put_ij();
v1.make_k();
cout << v1.get_k();
cout << "\n";
v2.f();
v2.put_ij();
return 0;
}
Поскольку класс Y наследует класс X со спецификатором доступа public, то защищенные элементы класса X становятся защищенными элементами класса Y. Это означает, что они могут далее наследоваться классом Z, и эта программа будет откомпилирована и выполнена корректно. Однако если изменить способ наследования X при объявлении Y на private, то, как показано в следующей программе, класс Z не имеет права доступа к i и j и к функциям get_ij() и put_ij(), поскольку они стали частными членами Y:
#include <iostream.h>
class X
{
protected:
int i, j;
public:
void get_ij()
{
cout << "Enter two numbers: ";
cin >> i >> j;
}
void put_ij() { cout << i << " " << j << "\n"; }
};
class Y: private X
{
int k;
public:
int get_k() { return k; }
void make_k() { k = i*j; }
};
class Z: public Y
{
public:
void f();
};
// теперь данная функция не работает
void Z::f()
{
// i = 2; i и j больше не доступны
// j = 3;
}
int main()
{
Y v1;
Z v2;
// v1.get_ij(); больше не доступна
// v1.put_ij(); больше не доступна
v1.make_k() ;
cout << v1.get_k();
cout << "\n";
v2.f(); // v2.put_ij(); больше не доступна
return 0;
}
Когда при объявлении класса Y перед базовым классом X имеется спецификатор доступа private, члены i, j, get_ij() и put_ij() становятся частными членами Y и поэтому не могут наследоваться классом Z, так что класс Z теперь не имеет к ним доступа.
При наследовании базового класса с ключевым словом private все его элементы, включая общедоступные члены, становятся частными элементами производного класса. Однако в определенных случаях может потребоваться, чтобы определенные общедоступные элементы базового класса сохранили свой статус общедоступных в производном классе. Для этого используется объявление доступа. Оно имеет следующую общую форму:
имя_базового_класса::элемент;
Объявление доступа помещается над подходящим заголовком при объявлении производного класса. Ниже представлен пример, иллюстрирующий использование объявления доступа:
#include <iostream.h>
class B
{
public:
int i, j;
};
class D: private B
{
public:
// объявление доступа
B::i; // i из класса B теперь опять публичный
int k;
};
int main()
{
D d;
d.i = 10; // допустимо, поскольку i сделан в D публичным
d.k = 20;
// d.j = 30; // недопустимо, поскольку j в D является частным
cout << d.i * d.k;
return 0;
}
В этом примере класс D наследуется от класса B с ключевым словом private. Это означает, что члены i и j становятся частными членами класса D. Однако в классе D объявление доступа указывает, что член i снова становится общедоступным.
Также можно использовать объявление доступа для того, чтобы предоставить защищенным членам базового класса статус защищенных в производном классе. Однако следует иметь в виду, что нельзя расширить доступ члена. Например, частный элемент базового класса не может стать публичным элементом производного класса.