Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
0
Добавлен:
31.05.2025
Размер:
307.9 Кб
Скачать

3. ДРУЖЕСТВЕННЫЕ ФУНКЦИИ И ДРУЖЕСТВЕННЫЕ КЛАССЫ

Одним из важных принципов С++ является возможность защиты данных от несанкционированного доступа, которая реализуется с помощью ключевого слова private. Возможны ситуации, когда необходимо, чтобы к закрытой части класса имела доступ функция, не являющаяся членом этого класса.

Функция – не член класса, получившая право доступа к закрытой части класса, называется дружественной функцией. Функция становится дружественной после описания при помощи ключевого слова friend.

Фрагмент: class CL { public:

friend void frd (void);

};

Причиной введения дружественных функций явилась ситуация, когда одна и та же функция должна использовать закрытые элементы двух и более классов.

Пример: два класса vector и matrix, каждый скрывает свое представление и предоставляет полный набор действий для манипуляций с объектами его типа.

vector – целочисленный массив из 4 элементов; индексы изменяются 0-3; matrix – массив из 4 векторов; индексы изменяются 0-3.

Доступ к элементам матрицы и вектора осуществляется через похожие функции elem.

int elem (int i);

int elem (int i, int y);

Задача: определить функцию, обеспечивающую умножение матрицы на вектор.

1. Способ. При помощи глобальной функции multiply() vector multiply(matrix &m, vector &v)

{vector r;

for (int i=0; i<3; i++){ r.elem (i) = 0;

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

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

}

return r;}

Способ не эффективен, так как приходится многократно вызывать функцию elem.

Если бы функция multiply была функцией–членом класса vector, то можно было бы без функции elem обращаться к элементам класса vector. Аналогично, если бы функция multiply была бы функцией–членом класса matrix. Обратиться одновременно к закрытым элементам нескольких классов может только дружественная функция.

2. Способ. При помощи дружественной функции. class vector {

int v[4];

…..

public:

friend vector multiply (matrix&, vectot&);

}

class matrix { int v[4][4];

…..

public:

friend vector multiply (matrix&, vector&);

}

vector multiply (matrix &m, vector &v){ vector r:

for (inti=0; i<=3; i++) { r.v [i] = 0;

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

}

return r;}

Дружественная функция не имеет никаких других особенностей, кроме права доступа к закрытой части класса. В данном примере обращение к элементам matrix и vector осуществляется непосредственно.

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

class x – дружественная для класса y.

{

void f ();

}; class y{

….

friend void x :: f ();

};

Дружественные классы.

Все функции–члены одного класса могут являться друзьями другого класса.

class x {…}; class y {

….

friend class x;

….

};

Есть класс x, и класс y, причём класс x является дружественным для класса y. Объявление класса “дружественный” предполагает, что закрытые и защищённые члены класса y могут использоваться в классе x.

4. УТОЧНЕНИЕ ИМЕНИ ЭЛЕМЕНТА.

Иногда полезно различать имена элементов класса и просто имена. Для этого используется операция двойное двоеточие (::) – разрешение области видимости.

Пример: class x{

int m; public:

int readm () {return x :: m;} void setm (int m)

{x :: m = m;}

};

В функцииx ::setm(), имя аргумента m, скрывает элемент m, так что ссылаться на него можно только по уточнённому имени x::m. Левым операндом (::) должно быть имя класса, если используется имя :: fun – это имя должно быть глобальным.

Наиболее часто такая запись используется для того, чтобы использовать имена общеизвестных функций (printf, open), как имена функции–членов.

Пример: class my_file

{

public:

int open (char *, char *);

}

int my_file :: open (char * name, char * spee)

{

if (:: open (name, flag)) {…}

};

5. СТАТИСТИЧЕСКИЕ ЭЛЕМЕНТЫ КЛАССА.

Класс – это тип, а не объект данных. Для каждого объекта класса существует своя копия элементов класса, но часто бывает необходимо, чтобы все объекты одного класса совместно пользовались одними данными. Это можно осуществить, используя глобальную переменную. Но иногда желательно объявить совместно используемые данные частью класса (обеспечить санкционированный доступ). Этого можно достигнуть, объявив соответствующие данные статистическими элементами класса.

Пример. Реализации списка всех задач. class task

{

task *next;

static task *task_chain; void schedule (int); void wait (event);

};

Описание task_chain, как статического элемента, обеспечивает условие, что цепочка задач будет всего одна, а не по одной копии на каждый объект task. Переменная находится в области действия класса task, обратиться из вне к ней нельзя (только объявив как public).

Использование статических объектов сокращает потребность глобальных переменных.

Соседние файлы в папке Информатика