Дружественные функции и классы
Дружественные функции
Дружественные функции применяются для доступа к скрытым полям класса и представляют альтернативу методам. Метод, как правило, описывает свойство объекта, а в виде дружественных функций оформляются действия, не являющиеся свойствами класса, но концептуально входящие в его интерфейс и нуждающиеся в доступе к его скрытым полям.
Особенности дружественных функций:
- дружественная функция объявляется внутри класса с ключевым словом friend. В качестве параметра ей должен передаваться объект или ссылка на объект класса, поскольку указатель this ей не передается;
- дружественная функция может быть обычной функцией или методом другого ранее определенного класса. На нее не распространяется действие спецификаторов доступа; место размещения ее объявления в классе безразлично;
- одна функция может быть дружественной сразу нескольким классам.
Пример
class monstr;
class hero {
public:
void rill (monstr &);
…
};
class monstr {
…
friend int steal_ammo (monstr &);
friend void hero: : kill (monstr &);
};
int steal_ammo (monstr &M) { return --ammo;}
void hero: : kill (monstr &M) {M.health=0; M.ammo=0;}
Пояснения
Функция kill является методом класса hero, а функция steal_ammo не принадлежит одному из классу.
Дружественный класс
Если все методы какого-либо класса должны иметь доступ к скрытым полям другого, весь класс объявляется дружественным с помощью ключевого слова friend.
class hero {
…
friend class mistress;
};
class mistress {
…
void f1 ( );
void f2 ( );
};
Функции f1 и f2 являются дружественными по отношению к классу hero.
!!! Объявление friend не является спецификатором доступа и не наследуется.
Деструкторы
Деструкторы – это особый вид метода, применяющийся для освобождения памяти, занимаемой объектом. Деструктор вызывается автоматически, когда объект выходит из области видимости:
- для локальных объектов – при выходе из блока, в котором они объявлены;
- для глобальных объектов – как часть процедуры выхода из main;
- для объектов, заданных через указатели, деструктор вызывается неявно при использовании операции delete.
Имя деструктора начинается с тильды (~), непосредственно за которой следует имя класса. Деструктор:
- не имеет аргументов и возвращаемого значения;
- не может быть объявлен как const или static;
- не наследуется;
- может быть виртуальным.
Если деструктор явно не определен, компилятор автоматически создает пустой деструктор.
Описывать явно деструктор требуется, когда объект содержит указатели на память, выделяемую автоматически.
Пример.Модифицированная структура monstr с полем name (см. ранее).
monstr: : ~ monstr ( ) {delete [ ] name;}
Деструктор можно вызвать явным образом путем указания полностью уточненного имени, например:
Monsr *m; …
m -> ~ monstr ( );
Задание
Добавьте в описание созданного вами класса деструктор.
Перегрузка операций
С++ позволяет переопределять действия большинства операций так, чтобы при использовании их с объектами конкретного класса они выполняли заданные функции. Это дает возможность использовать собственные типы данных как стандартные. Обозначения собственных операций вводить нельзя. Можно перегружать любые операции, за исключением:
. .* ? : : : # ## sizeof
Перегрузка операций осуществляется с помощью методов специального вида (функций-операций) и подчиняется следующим правилам:
- при перегрузке операций сохраняются количество аргументов, приоритеты операций и правила ассоциации (справа налево или слева направо), используемые в стандартных типах данных;
- для стандартных типов данных переопределять операции нельзя;
- функции-операции не могут иметь аргументов по умолчанию;
- функции-операции наследуются (за исключением =);
- функции-операции не могут определяться как static.
Функцию-операцию можно определить тремя способами: она должна быть либо методом класса, либо дружественной дружественной функцией класса, либо обычной функцией. В двух последних случаях функция должна принимать хотя бы один аргумент, имеющий тип класса, указателя или ссылки на класс.
Функция-операция содержит ключевое слово operator, за которым следует знак переопределяемой операции:
Тип operator (список параметров) {тело функции}