Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа №4,№5.pdf
Скачиваний:
107
Добавлен:
11.02.2015
Размер:
1.13 Mб
Скачать

Основы создания программ в Си

Page 39 of 58

в зависимости от того, какой вид операции используется — префиксный или постфиксный. Функциональный вызов для префиксной операции имеет форму

обьект.operator@()

Для постфиксной операции в функциональной форме вызова нужно задавать фиктивный аргумент:

объект.operator@(0);

Функциональная форма вызова для бинарной операции, определенной как метод класса, выглядит так:

обьект.operator@(аргумент)

Инфиксная форма

обьект @ аргумент

является сокращением функциональной.

Операции присваивания являются бинарными операциями, поэтому должны иметь один аргумент. Если операция присваивания operator» не реализуется явным образом, она создается автоматически по умолчанию. Для любого класса автоматически создаваемая операция присваивания имеет прототип

класс& operator=(const класс &r)

Допускается реализовать операцию присваивания с параметром и возвращаемым результатом не своего класса; разрешается передавать параметр любым способом; возвращать можно не ссылку, а значение или указатель — все зависит от потребностей задачи.

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

Money& Money::operator+=(const Money &b)

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

const Moneys Money::operator+=(const Money &b)

Модификатор const запрещает дальнейшую модификацию результата.

Функции-друзья класса

Любая внешняя функция, определенная как «друг» класса, имеет неограниченный доступ к любым элементам класса, в том числе и к закрытым. Для того чтобы внешняя функция стала другом класса, необходимо в интерфейсе класса задать ее прототип, добавив впереди слово friend, например

friend Money operator*(const long double &a, const Money &b);

Основы создания программ в Си

Page 40 of 58

При реализации функции слово friend писать запрещается. Не указывается также и префикс класса.

Рекомендуемые формы перегрузки операций для класса приведены в табл. 2.1. В частности, операции ввода/вывода operator» и operator« практически всегда реализуются как внешние дружественные функции. Например, для класса Two с двумя полями х и у целого типа эти функции могут выглядеть так:

ostream& operator<<(ostream& t, const Two &r)

{

return (t << ‘(‘ << r.x << ‘.’ << r.y << ‘)’ );

}

istream& operator>>(istream& t, Two &r)

{

t >> r.x >> r.y; return t;

}

Перегрузка операций методами класса и дружественными функциями показана в примере 2.3:

Пример 2.3 Перегрузка операций методами класса

class F

{

int f; int m;

public:

F(int t, int r = 0)

{

f = t; m = r;

}

~F(void);

F& operator++()

// префиксный инкремент

{ f++; return *this; }

 

F operator++(int)

// постфиксный инкремент

{

 

F t= *this;

 

f++;

 

return t;

 

}

 

F& operator+=(const F &r)

// сложение с присваиванием

{

 

Основы создания программ в Си

Page 41 of 58

 

 

 

f+=r.f;

m+=r.m; return *this;

}

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

friend F operator+(const F &l, const F &r);

friend ostream& operator<<(ostream& t, const F &r); friend istream& operator>>(istream& t, F &r);

};

// реализация дружественных функций

F operator+(const F &l, const F &r)

{

F t = l; t += r; return t;

}

// дружественные функции ввода/вывода ostream& operator<<(ostream& t, const F &r)

{

return (t << r.f << '/' << r.m);

}

istream& operator>>(istream& t, F &r)

{

t >> r.f >> r.m; return t;

}

F test;

cin >> test; cout << test;

Таблица 1 Форма перегрузки операций представлена ниже:

Таблица 1

Операция

Рекомендуемая форма перегрузки

 

 

Все унарные операции

Метод класса

 

 

 

Основы создания программ в Си

 

Page 42 of 58

 

 

 

 

 

 

= [] 0 -> -> *

 

Обязательно метод класса

 

 

 

 

 

 

 

+= -= *= /= %= &=

|= ^=

Метод класса

 

 

<<= >>=

 

 

 

 

 

 

 

 

 

Остальные бинарные операции

 

Внешняя функция-друг

 

 

 

 

 

 

Конструкторы и деструктор

Конструктор — это особый метод, имеющий имя, совпадающее с именем класса. Назначением конструктора является создание и инициализация объектов.

Количество и типы аргументов конструктора могут быть любые; конструктор может не иметь аргументов; аргументам разрешается присваивать значения по умолчанию; аргументы конструктора обычно используются для инициализации полей объекта. Конструктор не возвращает результата — нельзя писать даже void.

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

класс::класс(параметры)

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

конструктор без аргументов (конструктор по умолчанию);

конструктор инициализации;

конструктор копирования (с одним параметром определяемого класса).

При отсутствии в классе явно определенных конструкторов автоматически создаются конструктор без аргументов (конструктор по умолчанию) и конструктор копирования. Создаваемый автоматически конструктор без аргументов имеет вид

класс::класс() {}

Конструктор копирования автоматически создается в таком виде:

класс::класс (const класс &г)

{

*this = г ;

}

Аргументом конструктора копирования всегда является объект своего класса.

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

date d;

// конструктор без аргументов

 

 

Основы создания программ в Си

Page 43 of 58

 

 

 

date

t(d);

//

конструктор

копирования

date

r = d;

//

конструктор

копирования

 

 

 

 

 

При наличии хотя бы одного явно определенного конструктора конструктор без аргументов не создается. Конструктор копирования создается всегда, если не определен явно.

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

Любой конструктор с параметрами не своего класса является конструктором инициализации. Конструктор инициализации предназначен для инициализации полей класса.

class time

 

{

 

public:

 

time();

// конструктор без аргументов

time(int h, int m = 0, int s = 0)

// конструктор инициализации

{

 

hours = h;

 

minutes = m;

 

seconds = s;

 

}

 

private:

 

int hours, minutes, seconds;

// закрытые поля

};

 

time::time()

// реализация вне класса

{ hours = minutes = seconds = 0; }

 

 

 

Конструктор инициализации обеспечивает объявление и инициализацию переменных:

time t(2,59,59), s(13,45), u = 14;

Конструктор инициализации может вызываться явно:

time R = time(10);

// явный вызов конструктора

 

 

Конструктор инициализации со всеми аргументами по умолчанию играет роль конструктора без аргументов (конструктора по умолчанию).

Основы создания программ в Си

 

Page 44 of 58

 

 

 

 

Конструкторы вызываются и при создании динамических переменных.

 

 

 

 

 

 

time *а = new time;

//

конструктор без аргументов

 

 

time *b = new time();

//

конструктор без аргументов

 

 

time *d = new time(12,23);

//

конструктор инициализации

 

 

 

 

 

 

 

time *f = new time(*d);

//

конструктор копирования

 

 

 

 

 

 

Конструкторы обеспечивают привычную форму объявления констант:

const time d2(100,67);

// конструктор инициализации

const time

d0

= 100:

// конструктор

инициализации

const time

d5

= time(100);

// явный вызов

 

 

 

 

 

 

Конструктор инициализации обеспечивает инициализацию массива:

time Т[3] = { 1, 2, 3 }:

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

time T[0] = time(l);

time T[l] = time(2);

time T[2] = time(3);

Если массив не инициализируется, то для каждого элемента массива вызывается конструктор без аргументов, если он определен явно или неявно (или вызывается конструктор инициализации с аргументами по умолчанию).

Деструктор — это метод, имеющий имя класса, с тем отличием, что его первым символом должен быть символ - (тильда). Деструктор не возвращает результата и не имеет аргументов. Деструктор в классе может быть только один — перегрузка деструкторов запрещена. Деструктор вызывается автоматически при каждом уничтожении объекта. При отсутствии в классе явно определенного деструктора он создается автоматически. Вид автоматически создаваемого деструктора следующий:

класс::~класс(){}

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