Бьерн Страуструп. Язык программирования С++



бет53/124
Дата16.07.2016
өлшемі3.27 Mb.
#204081
түріКнига
1   ...   49   50   51   52   53   54   55   56   ...   124

6.6 Контроль доступа


Член класса может быть частным (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; // нормально

}



Достарыңызбен бөлісу:
1   ...   49   50   51   52   53   54   55   56   ...   124




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет