Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
umm_3690.pdf
Скачиваний:
24
Добавлен:
30.04.2015
Размер:
364.53 Кб
Скачать

Деструкторы

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

– для локальных объектов – при выходе из блока, в котором они объявле-

ны;

для глобальных объектов – как часть процедуры выхода из main;

для объектов, заданных через указатели, деструктор вызывается неявно при использовании операции delete.

Имя деструктора начинается с тильды(~), непосредственно за которой следует имя класса. Деструктор:

не имеет аргументов и возвращаемого значения;

не может быть объявлен как const или static;

не наследуется;

может быть виртуальным.

Если деструктор явно не определен, компилятор автоматически создает пустой деструктор.

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

Пример. Модифицированная структура monstr с полем name (см. ранее). monstr:: ~ monstr ( ) {delete [ ] name;}

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

monstr *m; …

m -> ~ monstr ( );

Задание

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

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

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

. .* ?: :: # ##

sizeof

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

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

16

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

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

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

функции-операции не могут определяться как 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;}

17

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

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 ( );

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

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

class monstr {

bool operator > (const monstr &M) {

if (health >M.get_health ( ) ) return true;

return false;

}

};

18

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

bool operator > (const monstr &M1, const monstr &M2) {

if (M1.get_health ( ) > M2.get_health ( )) return true;

return false;

}

Перегрузка операции присваивания

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

– ссылку на присваиваемый объект.

class monstr &operator = (const monstr &M) {

//

if (&M= =this) return *this;

if (name) delete [ ] name; //

if (M.name) {

name = new char [strlen(M.name) c+1];

strcpy (name, M.name;}

else name =0;

health = M.health; ammo = M.ammo;

skin = M.skin;

return *this;

}

Возврат из функции указателя на объект делает возможной цепочку операций присваивания:

monstr A(10), B, C; C = B = A;

Операцию присваивания можно определять только как метод класса. Она не наследуется.

19

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]