Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы на вопросы Осадчий А.В. гр.010902.docx
Скачиваний:
6
Добавлен:
24.04.2019
Размер:
143.34 Кб
Скачать

18. Дружественные функции и дружественные классы.

Данные(внутренние переменные) объекта защищены от воздействий из вне и доступ к ним можно получить только с помощью методов(функций) объекта. Но бывают такие случаи, когда нам необходимо получить доступ к данным объекта не используя его интерфейс. Зачем это может понадобиться ? Как я уже как-то упоминал, при доступе к внутренним переменным объекта через его методы уменьшается эффективность работы за счет затрат на вызов метода. В большинстве случаев нам это не критично, но не всегда. В некоторых случаях это может играть существенную роль. Конечно, можно добавить новый метод к классу для получения прямого доступа к внутренним переменным. Однако, в большинстве случаев, интерфейс объекта (методы) спланирован для выполнения определенного круга операций, и наша функция может оказаться как бы ни к месту. А если хуже того, нам необходимо получить прямой доступ к внутренним данным двух разных объектов ? Возникает проблема. Именно для решения подобных задач и существует возможность описание функции, метода другого класса или даже класса как дружественного(friend).

Для описания дружественной тому или иному классу функции(метода или класса) необходимо в описании этого класса объявить (описать) дружественную функцию с указанием ключевого слова friend. Если функция дружественна нескольким классам, то надо добавить это описание во все классы, к внутренним данным которых производим обращение. В большинстве языков ООП не имеет различия в какой раздел описания класса(publuc, protected или private) вставлено описание дружественной функции.Но возникает такой вопрос: А как же наша хваленая защищенность данных, если можно получить доступ к данным напрямую ?Но оказывается, что с точки зрения применимости механизма инкапсуляции, защищенность данных сохраняется, поскольку полностью исключается всякая возможность доступа к данным так, чтобы объект не был осведомлен об этом.

class A // Описание класса A

{

//...

void z(); // Описание функции z класса A

};

class B // Описание класса B

{

//...

friend void A::z(); // Описание функции z класса A как дружественной

// классу B, т.е. из функции z класса A можно

// получить доступ к внутренним переменным класса B

};

class C // Описание класса C

{

//...

friend class A; // Описание класса A как дружественного классу C,

// все функции класса A будут дружественны классу C и

// из любой функции класса A можно получить доступ к

// внутренним переменным класса C

}

19. Использование указателя this.

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

Для любой функции, принадлежащей классу my_class, указатель this неявно объявлен так: my_class *const this;

this – это указатель на экземпляр объекта, для которого выполняется текущий метод. Чаще всего его использовать не нужно, так как к полям и методам объекта можно обращаться просто по имени. Его использование обязательно при конфликте имен.

this есть указатель на объект, метод которого вызывается (this можно использоваться только в методах). Чаще всего без него вообще можно обойтись, если только не надо передавать указатель явным образом (как входной параметр в функцию или метод).

допустим есть класс myCl

class myCl

{

public:

int a;

void func(int); //Прототип

};

далее в какой-либо функции описываем объект данного класса и вызываем функцию func():

int main()

{

int x=3;

myCl A;

A.func(x); //вызов функции func;

return 0;

}

Таким образом в функцию func() передается параметр x, а также передается указатель на A (не явно) - это и есть указатель this.

Теперь пример функции func:

void func(int x)

{

//Сейчас указатель this указывает на A

//Можно это использовать так:

this->a=x;

//Конечно, можно было бы просто написать

//a=x;

//Но в некоторых случаях использование указателя this необходимо

//например в перегрузке операции присваивания,

//для возможности многократного присваивания

};