Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по С++ глава 5.doc
Скачиваний:
3
Добавлен:
05.11.2018
Размер:
166.91 Кб
Скачать

5. Перегрузка, копирование и преобразование

В этой главе рассмотрены способы настройки созданных классов. Особое внимание уделено процедуре перегрузки (overloading) стандартных операторов языка C++, позволяющей описывать их поведение при работе с объектами классов. Рассмотрено также определение специальных конструкторов, инициализирующих объект класса другим объектом такого же типа (конструкторы копирования – copy constructors) или преобразовывающих данные различных типов в объект класса (конструкторы преобразования – conversion constructors).

5.1. Перегрузка операторов

Операторы C++ применяются к данным встроенных типов заранее определенным способом. Например, при применении операции сложения к двум переменным типа int выполняется целочисленное сложение, а при использовании оператора «+» для двух переменных типа double – операция сложения с плавающей запятой. В языке C++ допустимо применение стандартных операторов к объектам классов при условии точного описания их действия. Определение способа работы оператора с объектами конкретного класса называется перегрузкой оператора.

Предположим, имеется класс CCurrency, предназначенный для хранения и обработки денежных сумм.

class CCurrency

{

private:

long Dollars;

int Cents;

public:

CCurrency ()

{

Dollars = Cents = 0;

}

CCurrency (long Dol, int Cen)

{

SetAmount (Dol, Cen);

}

void GetAmount (long *PDol, int *PCen)

{

*PDol = Dollars;

*PCen = Cents;

}

void PrintAmount ()

{

cout.fill('0');

cout.width(1);

cout << '$' << Dollars << '.';

cout.width(2);

cout << Cents << '\n';

}

void SetAmount (long Dol, int Cen)

{

// проверка суммы центов, которая превышает 100:

Dollars = Dol + Cen / 100;

Cents = Cen % 100;

}

};

В классе CCurrency денежные суммы хранятся в виде целочисленных величин, предназначенных для последующей обработки с использованием быстродействующих целочисленных операций. Класс содержит конструктор по умолчанию для установки начальных значений переменных, содержащих количество долларов и центов, в 0 и конструктор для присвоения этим переменным конкретных значений. Предусмотрены отдельная функция-член (SetAmount) для задания величины денежной суммы и функции-члены GetAmount и PrintAmount для подсчета суммы и ее печати соответственно. Заметим: можно хранить значение суммы в одной переменной long integer в виде общей суммы в центах, что позволяет обрабатывать большие числа. Однако предпочтительнее для хранения величины, обозначающей количество долларов, использовать переменную типа long, а для центов – переменную типа int. В результате можно будет оперировать количеством долларов, достигающим максимальной величины типа long, что в системе программирования C++ составляет 2147483647.

Примечание

Несмотря на то, что в Visual C++ 6 размер переменной типа int совпадает с размером переменной типа long (4 байта), переменная Dollars явно объявлена как переменная типа long для того, чтобы она могла содержать максимально возможные целочисленные значения при использовании любого компилятора.

Вместо задания функций-членов для арифметических операций с денежными суммами, можно перегрузить стандартные операторы C++. Это позволяет выполнять арифметические действия, применяя выражения, традиционно используемые для встроенных типов данных. Для перегрузки оператора определяется функция с именем operator, за которым следует обозначение операции. Например, можно перегрузить оператор «+», добавив в определение класса CCurrency следующую функцию-член.

class CCurrency

{

// другие объявления ...

public:

CCurrency operator+ (CCurrency Curr)

{

CCurrency Temp (Dollars + Curr.Dollars, Cents + Curr.Cents);

return Temp;

}

// другие объявления ...

};

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

CCurrency Amount1 (12, 95);

CCurrency Amount2 (4, 38);

CCurrency Total;

Total = Amountl + Amount2;

Компилятор языка C++ интерпретирует выражение Amountl + Amount2 как

Amountl.operator+ (Amount2);

Функция operator+ создает временный объект Temp класса CCurrency, содержащий размер денежной суммы, полученной в результате сложения двух объектов. Затем она возвращает временный объект. Кроме того, приведенное выше выражение присваивает возвращаемый объект экземпляру Total класса CCurrency. Такой способ присваивания делает возможным поэлементное копирование компилятором переменных-членов одного класса в другой.

Подобно стандартной операции сложения, выражение, содержащее более одного перегруженного оператора «+», вычисляется слева направо. Например, следующая программа использует перегруженный оператор для сложения величин, хранимых в трех объектах класса CCurrency.

void main()

{

CCurrency Advertising (235, 42);

CCurrency Rent (823, 68);

CCurrency Entertainment (1024, 32);

CCurrency Overhead;

Overhead = Advertising + Rent + Entertainment;

Overhead.PrintAmount();

}

Функцию operator+ можно упростить, заменив локальный временный объект класса CCurrency неявным временным объектом.

CCurrency operator+ (CCurrency Curr)

{

return CCurrency (Dollars + Curr.Dollars, Cents + Curr.Cents);

}

При вызове конструктора класса компилятор из выражения создает временный объект класса. Функция operator+ непосредственно возвращает содержимое этого временного объекта. Далее, в параграфе «Конструкторы копирования», описано, как объекты класса возвращаются функциями.

Функцию operator+ можно реализовать более эффективно, передавая ей ссылку на объект класса CCurrency, а не сам объект. Передача ссылок исключает необходимость копирования объекта в локальный параметр, что особенно важно для объектов больших размеров (см. гл. 2). Следующий фрагмент программы является окончательной версией функции operator+

CCurrency operator+ (const CCurrency &Curr)

{

return CCurrency (Dollars + Curr.Dollars, Cents + Curr.Cents);

}

Использование спецификатора const при объявлении параметра – гарантия того, что функция не изменит значение параметра.