Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c++book1.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
2 Мб
Скачать
☆

5.4 Друзья и Объединения

В этом разделе описываются еще некоторые особенности, ка­сающиеся классов. Показано, как предоставить функции не члену доступ к закрытым членам. Описывается, как разрешать конфлик­ты имен членов, как можно делать вложенные описания классов, и как избежать нежелательной вложенности. Обсуждается также, как объекты класса могут совместно использовать члены данные, и как использовать указатели на члены. Наконец, приводится пример, показывающий, как построить дискриминирующее (эконом­ное) объединение.

5.4.1 Друзья

Предположим, вы определили два класса, vector и matrix (вектор и матрица). Каждый скрывает свое представление и пре­доставляет полный набор действий для манипуляции объектами его типа. Теперь определим функцию, умножающую матрицу на вектор. Для простоты допустим, что в векторе четыре элемента, которые индексируются 0...3, и что матрица состоит из четырех векторов, индексированных 0...3. Допустим также, что доступ к элементам вектора осуществляется через функцию elem(), кото­рая осуществляет проверку индекса, и что в matrix имеется аналогичная функция. Один подход состоит в определении гло­бальной функции multiply() (перемножить) примерно следующим образом:

vector multiply(matrix& m, vector& v);

(*

vector r;

for (int i = 0; i<3; i++) (* // r[i] = m[i] * v;

r.elem(i) = 0;

for (int j = 0; j<3; j++)

r.elem(i) += m.elem(i,j) * v.elem(j);

*)

return r;

*)

Это своего рода "естественный" способ, но он очень неэф­фективен. При каждом обращении к multiply() elem() будет вы­зываться 4*(1+4*3) раза.

Теперь, если мы сделаем multiply() членом класса vector, мы сможем обойтись без проверки индексов при обращении к эле­менту вектора, а если мы сделаем multiply() членом класса matrix, то мы сможем обойтись без проверки индексов при обра­щении к элементу матрицы. Однако членом двух классов функция быть не может. Нам нужно средство языка, предоставляющее функции право доступа к закрытой части класса. Функция не член, получившая право доступа к закрытой части класса, назы­вается другом класса (friend). Функция становится другом класса после описания как friend. Например:

class matrix;

class vector (*

float v[4];

// ...

friend vector multiply(matrix&, vector&);

*);

class matrix (*

vector v[4];

// ...

friend vector multiply(matrix&, vector&);

*);

Функция друг не имеет никаких особенностей, помимо права доступа к закрытой части класса. В частности, friend функция не имеет указателя this (если только она не является полноп­равным членом функцией). Описание friend - настоящее описа­ние. Оно вводит имя функции в самой внешней области видимости программы и сопоставляется с другими описаниями этого имени. Описание друга может располагаться или в закрытой, или в отк­рытой части описания класса. Где именно, значения не имеет.

Теперь можно написать функцию умножения, которая исполь­зует элементы векторов и матрицы непосредственно:

vector multiply(matrix& m, vector& v);

(*

vector r;

for (int i = 0; i<3; i++) (* // r[i] = m[i] * v;

r.v[i] = 0;

for (int j = 0; j<3; j++)

r.v[i] += m.v[i][j] * v.v[j];

*)

return r;

*)

Есть способы преодолеть эту конкретную проблему эффек­тивности не используя аппарат friend (можно было бы определить операцию векторного умножения и определить multiply() с ее помощью). Однако существует много задач, ко­торые проще всего решаются, если есть возможность предоста­вить доступ к закрытой части класса функции, которая не явля­ется членом этого класса. В Главе 6 есть много примеров применения friend. Достоинства функций друзей и членов будут обсуждаться позже.

Функция член одного класса может быть другом другого. Например:

class x (*

// ...

void f();

*);

class y (*

// ...

friend void x::f();

*);

Нет ничего необычного в том, что все функции члены одно­го класса являются друзьями другого. Для этого есть даже бо­лее краткая запись:

class x (*

friend class y;

// ...

*);

Такое описание friend делает все функции члены класса y друзьями x.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]