Член класса может быть частным (private), защищенным (protected)
или общим (public):
Частный член класса X могут использовать только функции-члены и
друзья класса X.
Защищенный член класса X могут использовать только функции-члены
и друзья класса X, а так же функции-члены и друзья всех
производных от X классов (см. $$5.4.1).
Общий член можно использовать в любой функции.
Эти правила соответствуют делению обращающихся к классу функций на три
вида: функции, реализующие класс (его друзья и члены), функции,
реализующие производный класс (друзья и члены производного класса) и
все остальные функции.
Контроль доступа применяется единообразно ко всем именам. На
контроль доступа не влияет, какую именно сущность обозначает имя.
Это означает, что частными могут быть функции-члены, константы и т.д.
наравне с частными членами, представляющими данные:
class X {
private:
enum { A, B };
void f(int);
int a;
};
void X::f(int i)
{
if (i
a++;
}
void g(X& x)
{
int i = X::A; // ошибка: X::A частный член
x.f(2); // ошибка: X::f частный член
x.a++; // ошибка: X::a частный член
}
6.6.1 Защищенные члены
Дадим пример защищенных членов, вернувшись к классу window из
предыдущего раздела. Здесь функции _draw() предназначались только для
использования в производных классах, поскольку предоставляли неполный
набор возможностей, а поэтому не были достаточны удобны и
надежны для общего применения. Они были как бы строительным
материалом для более развитых функций. С другой стороны, функции draw()
предназначались для общего применения. Это различие можно выразить,
разбив интерфейсы классов window на две части - защищенный интерфейс
и общий интерфейс:
class window {
public:
virtual void draw();
// ...
protected:
void _draw();
// другие функции, служащие строительным материалом
private:
// представление класса
};
Такое разбиение можно проводить и в производных классах, таких, как
window_w_border или window_w_menu.
Префикс _ используется в именах защищенных функций, являющихся
частью реализации класса, по общему правилу: имена, начинающиеся с _ ,
не должны присутствовать в частях программы, открытых для общего
использования. Имен, начинающихся с двойного символа подчеркивания,
лучше вообще избегать (даже для членов).
Вот менее практичный, но более подробный пример:
class X {
// по умолчанию частная часть класса
int priv;
protected:
int prot;
public:
int publ;
void m();
};
Для члена X::m доступ к членам класса неограничен:
void X::m()
{
priv = 1; // нормально
prot = 2; // нормально
publ = 3; // нормально
}
Член производного класса имеет доступ только к общим и защищенным
членам:
class Y : public X {
void mderived();
};
Y::mderived()
{
priv = 1; // ошибка: priv частный член
prot = 2; // нормально: prot защищенный член, а
// mderived() член производного класса Y
publ = 3; // нормально: publ общий член
}
В глобальной функции доступны только общие члены:
void f(Y* p)
{
p->priv = 1; // ошибка: priv частный член
p->prot = 2; // ошибка: prot защищенный член, а f()
// не друг или член классов X и Y
p->publ = 3; // нормально: publ общий член
}
6.6.2 Доступ к базовым классам
Подобно члену базовый класс можно описать как частный, защищенный
или общий:
class X {
public:
int a;
// ...
};
class Y1 : public X { };
class Y2 : protected X { };
class Y3 : private X { };
Поскольку X - общий базовый класс для Y1, в любой функции, если есть
необходимость, можно (неявно) преобразовать Y1* в X*, и притом
в ней будут доступны общие члены класса X:
void f(Y1* py1, Y2* py2, Y3* py3)
{
X* px = py1; // нормально: X - общий базовый класс Y1
py1->a = 7; // нормально
px = py2; // ошибка: X - защищенный базовый класс Y2
py2->a = 7; // ошибка
px = py3; // ошибка: X - частный базовый класс Y3
py3->a = 7; // ошибка
}
Теперь пусть описаны
class Y2 : protected X { };
class Z2 : public Y2 { void f(); };
Поскольку X - защищенный базовый класс Y2, только друзья и члены Y2,
а также друзья и члены любых производных от Y2 классов (в частности
Z2) могут при необходимости преобразовывать (неявно) Y2* в X*.
Кроме того они могут обращаться к общим и защищенным членам класса X:
void Z2::f(Y1* py1, Y2* py2, Y3* py3)
{
X* px = py1; // нормально: X - общий базовый класс Y1
py1->a = 7; // нормально
px = py2; // нормально: X - защищенный базовый класс Y2,
// а Z2 - производный класс Y2
py2->a = 7; // нормально
px = py3; // ошибка: X - частный базовый класс Y3
py3->a = 7; // ошибка
}
Наконец, рассмотрим:
class Y3 : private X { void f(); };
Поскольку X - частный базовый класс Y3, только друзья и члены Y3
могут при необходимости преобразовывать (неявно) Y3* в X*.
Кроме того они могут обращаться к общим и защищенным членам
класса X:
void Y3::f(Y1* py1, Y2* py2, Y3* py3)
{
X* px = py1; // нормально: X - общий базовый класс Y1
py1->a = 7; // нормально
px = py2; // ошибка: X - защищенный базовый класс Y2
py2->a = 7; // ошибка
px = py3; // нормально: X - частный базовый класс Y3,
// а Y3::f член Y3
py3->a = 7; // нормально
}
Достарыңызбен бөлісу: |