23 Виртуальные базовые классы. "Друзья" классов (friend).

При множественном наследовании базовый класс не может быть задан в производном классе более одного раза

class В { ... };

class D : В, В {…}: // недопустимо

Однако базовый класс может быть передан производному классу более одного раза косвенно

class Х : publ ic В {...}

class Y : public В { ... }

class Z : public X, public Y {…} // ДОПУСТИМО

В данном случае каждый объект класса Z будет иметь два подобъекта класса В. Если это вызывает проблемы, к спецификатору базового класса может быть добавлено ключевое слово virtual, например:

class X : virtual public B {…}

class Y : virtual public B {…}

class Z : public X, public Y {…}

Теперь B является виртуальным базовым классом, а класс Z имеет только один подобъект класса В.

"Друзья" классов (friend)

Friend F класса X — это функция или класс, которые, не являясь методом X. имеют полные права доступа к private и protected компонентам X. Во всех прочих отношениях F — это с точки прения области действия, объявлений и определений обычная функция.

Поскольку F не является элементом X, она не лежит в области действиях и поэтому не может вызываться операциями выбора x.F и xptr->F (где х — объект X, a xptr — указатель объекта X).

Если в объявлении или определении функции в пределах класса Х используется спецификатор friend, то такая функция становится "другом" класса X.

Дружественная функция, определенная в пределах класса. подчиняется тем же правилам встраивания, что и методы (см. "Встраиваемые функции").

Функции-"друзья" не зависят от их позиции в классе и спецификаторов доступа, например:

class Х {

int i;  // private относительно Х

friend void friend_func(X*,  int);

/* friend_func не является private */

public:

void member_func (int);

};

/* определения; для обеих функций отметим доступ к private int i */

void friend_func(X* xptr, int a) { xptr->i=a; }

void X::member_func(int a) { i=a; }

X xobj;

/* отметим различие в вызовах функций */ (

friend_func(&xobj,6);

xobj.member_func(6);

Можно сделать все функции класса Y друзьями класса Х в одном объявлении

class Y; // неполное объявление

class Х {

friend Y;

int i;

void member_funcX();

};

class Y; { // полное объявление

void friend_X1(X&);

void friend_ X2(X*);

};

Функции, объявленные в Y, являются друзьями X, хотя они и не имеют спецификаторов friend. Они имеют доступ к private элементам X, таким, как i и member_funcX.

Отдельные методы Х также могут быть друзьями класса Y

class Х {

void member_funcX();

}

class Y {

int i;

friend void X::member_funcX();

};

"Дружба" классов не транзитивна: если Х друг Y, a Y друг Z, это не означает, что Х друг Z. Однако "дружба" наследуется.

Hosted by uCoz