Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование_на_С++_Ч2_ООП.doc
Скачиваний:
54
Добавлен:
22.02.2015
Размер:
633.34 Кб
Скачать

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

Если все методы какого-либо класса должны иметь доступ к скрытым полям другого, весь класс объявляется дружественным с помощью ключевого слова 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;}

Деструктор можно вызвать явным образом путем указания полностью уточненного имени, например:

monstr *m; …

m -> ~ monstr ( );

Задание

Добавьте в описание созданного вами класса деструктор.

Перегрузка операций

С++ позволяет переопределять действия большинства операций так, чтобы при использовании их с объектами конкретного класса они выполняли заданные функции. Это дает возможность использовать собственные типы данных как стандартные. Обозначения собственных операций вводить нельзя. Можно перегружать любые операции, за исключением:

. .* ?: :: # ## sizeof

Перегрузка операций осуществляется с помощью методов специального вида (функций-операций) и подчиняется следующим правилам:

– при перегрузке операций сохраняются количество аргументов, приоритеты операций и правила ассоциации (справа налево или слева направо), используемые в стандартных типах данных;

– для стандартных типов данных переопределять операции нельзя;

– функции-операции не могут иметь аргументов по умолчанию;

– функции-операции наследуются (за исключением =);

– функции-операции не могут определяться как static.

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

Функция-операция содержит ключевое слово operator, за которым следует знак переопределяемой операции:

Тип operator (список параметров) {тело функции}

Перегрузка унарных операций

Унарная функция-операция, определяемая внутри класса, должна быть представлена с помощью нестатического метода без параметров, при этом операндом является вызвавший ее объект, например:

class monstr {

monstr & operator ++ ( ) {++ health; return *this;}

};

monstr Vasia;

cout << (++Vasia).get_health ( );

Если функция определяется вне класса, она должна иметь один параметр типа класса:

class monstr {

friend monstr & operator ++ (monstr &M);

};

monstr &operator ++ (monstr &M) {++ M.health; return M;}

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

void change_health (in the) {health=he;}

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

monstr &operator ++ (monstr &M) {

int h=M.get_health ( ); h++;

M.change_health (h);

return M;

}

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

class monstr {

monstr operator ++ (int) {

monstr M(*this); health ++;

return M;

}

};

monstr Vasia;

cout <<(Vasia++).get_health ( );