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

Дружественные функции

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

Особенности дружественных функций:

- дружественная функция объявляется внутри класса с ключевым словом 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 (список параметров) {тело функции}

Наши рекомендации