using namespace std;
:
class Date
{
private:
6:
|
int Day; //
|
Диапазон:
|
1 - 3 0 (Давайте предположим, что у всех
|
|
//
|
месяцев по
|
30 дней)
|
int Month;
int Year;
public:
// Конструктор, инициализирующий объект днем, месяцем и годом
Date (int InputDay, int InputMonth, int InputYear)
: Day (InputDay), Month (InputMonth), Year (InputYear) {};
// Унарный оператор инкремента (префиксный)
Dates operator ++ ()
{
++Day;
return *this;
20: }
2 1 :
// Унарный оператор декремента (префиксный)
Dates operator — ()
{
— Day;
return *this;
}
28:
void DisplayDate ()
{
cout « Day « " / ” « Month « " / " « Year « endl;
}
};
int main ()
{
// Создать экземпляр и инициализировать его // датой 25 декабря 2011 года
Date Holiday (25, 12, 2011);
39:
cout « "The date object is initialized to: ";
Holiday.DisplayDate ();
42:
// Применение префиксного оператора
++ Holiday;
45:
cout « "Date after prefix-increment is: ";
// Отображение даты после инкремента
Holiday.DisplayDate ();
50:
— Holiday;
— Holiday;
cout « "Date after two prefix-decrements is: ";
55:
|
Holiday.DisplayDate ();
|
*
|
56:
|
|
|
return 0;
}
Результат
The date object is initialized to: 25 / 12 / 2011
Date after prefix-increment is: 26 / 12 / 2011
Date after two prefix-decrements is: 24 / 12 / 2011
Анализ
Представляющие интерес операторы находятся в строках 16-27 и обеспечивают инкре мент и декремент объектов класса D ate при добавлении и вычитании дня, как показано
строках 44, 51 и 52 функции m ain (). Префиксные операторы инкремента сначала вы полняют приращение, а затем возвращают ссылку на тот же объект.
ПРИМЕЧАНИЕ
У этой версии класса даты минимальная реализация, практически пустая, что бы сократить количество строк при объяснении реализации префиксных опе раторов (++) и (— ). При этом я подразумевал, что месяц имеет 30 дней, и не реализовал функциональные возможности перевода месяца и года.
Для обеспечения постфиксного инкремента и декремента достаточно добавить в класс
D ate следующий код:
постфиксный оператор отличается от префиксного типом
возвращаемого значения и параметром
306 ЗАНЯТИЕ 12. Типы операторов и их перегрузка
Date operator ++ (int)
{
Сохранить копию текущего состояния объекта, прежде чем
увеличить день
Date Copy (Day, Month, Year);
++Day;
Возвратить состояние прежде, чем выполнить инкремент return Сору;
}
постфиксный оператор декремента Date operator — (int)
{
Date Copy (Day, Month, Year);
— Day; return Copy;
}
Когда ваша версия класса D ate будет поддерживать префиксные и постфиксные опе раторы инкремента и декремента, вы будете в состоянии использовать объекты класса следующим образом:
Date Holiday (25, 12, 2011); // создание экземпляра
++ Holiday; // использование префиксного оператора инкремента ++
Holiday ++; // использование постфиксного оператора инкремента ++
— Holiday; // использование префиксного оператора декремента —
Holiday — ; // использование постфиксного оператора декремента —
ПРИМЕЧАНИЕ
Как демонстрирует реализация постфиксных операторов, перед операцией инкремента или декремента создается копия, содержащая текущее состояние объекта; она и будет возвращена.
Другими словами, если вам нужен только инкремент, выбирайте оператор ++ объект; а не объект ++;, чтобы избежать создания временной копии, ко торая не используется.
Создание операторов преобразования
Если в код функции m ain () из листинга 12.1 добавить строку
cout « Holiday; // ошибка из-за отсутствия оператора преобразования
то произойдет отказ компиляции с сообщ ением
|
e r r o r : b i n a r y
|
' « '
|
: no o p e r a t o r
|
fo u n d
|
w h ich ta k e s
|
a r i g h t - h a n d o p e ra n d
|
o f
|
ty p e ' D a te ' (o r
|
t h e r e
|
i s no a c c e p t
|
a b l e
|
c o n v e r s io n )
|
(ошибка: b i n a r y ' « '
|
: не найден оператор, получающий правый
|
операнд типа ' D a te 1 (или нет приемлемого преобразования)). По существу, это сообще ние означает, что оператор c o u t не знает, как интерпретировать экземпляр класса D ate, поскольку он не поддерживает подходящих операторов.
Унарные операторы
307
Однако оператор c o u t вполне может работать с константной строкой типа c o n s t ch a r* :
std::cout « "Hello world"; // const char* работает!
Поэтому, чтобы оператор c o u t работал с объектом класса D ate, достаточно добавить оператор, который возвращает его версию типа c o n s t c h a r* :
operator const char*()
{
// реализация оператора, возвращающая char*
}
Листинг 12.2 демонстрирует пример реализации этого оператора.
ЛИСТИНГ 12.2. Реализация оператора преобразования в co n st char* для класса Date
#include
#include
#include
using namespace std;
class Date
6 : {
private:
8:
|
int Day; //
|
Диапазон:
|
1 - 3 0 (Давайте предположим, что у всех
|
|
//
|
месяцев по
|
30 дней)
|
int Month;
int Year;
1 1 :
string DatelnString;
public:
15:
// Конструктор, инициализирующий объект днем, месяцем и годом
Date (int InputDay, int InputMonth, int InputYear)
: Day (InputDay), Month (InputMonth), Year (InputYear) {};
operator const char*()
21: {
ostringstream formattedDate;
23:
|
formattedDate « Day « " / " « Month « " / " « Year;
|
24:
|
|
DatelnString = formattedDate.str();
return DatelnString.c_str();
}
};
29:
int main ()
{
32: // Создатьэкземпляр и инициализировать его
датой 25 декабря 2011 года
Date Holiday (25, 12,2011);
cout « "Holiday is on: " « Holiday « endl;
return 0;
}
308 ЗАНЯТИЕ 12. Типы операторов и их перегрузка
Результат
Holiday is on: 25 / 12 / 2011
Анализ
П реим ущ ество реализации оператора c o n s t c h a r * (строки 20 -27) проявляет
ся в строке 35 функции m ain (). Теперь экземпляр класса D a te может непосредствен
но использоваться в операторе c o u t благодаря тому факту, что он понимает тип c o n s t
c h a r* . Компилятор автоматически использует вывод подходящего (а в данном случае единственно доступного) оператора и передает его оператору c o u t, который отобража ет дату на экране. В нашей реализации оператора c o n s t c h a r* использован оператор
s t d : : o s tr in g s t r e a m , преобразующий целые числа члена класса в объект s t d : : s t r i n g (строки 23 и 25). Можно было бы сразу вернуть результат метода f o r m a tte d D a te . s t r (), но мы сохраняем его копию в закрытом члене D a te :: D a te ln S tr in g (строка 25), посколь ку переменная f o rm a tte d D a te является локальной, она удаляется при выходе из операто ра. Так, указатель, полученный от метода s t r (), после выхода будет недействителен.
Этот оператор открывает новые возможности использования класса D ate . Теперь дату можно даже присвоить непосредственно строке:
Do'stlaringiz bilan baham: |