Date
Date
и все функции-члены написаны правильно, то мы никогда не получим объект класса Date
с неверным значением. Итак, следует предотвратить создание неправильных объектов класса Date
.// простой класс Date (предотвращаем неверные даты)
class Date {
public:
class Invalid { }; // используется как исключение
Date(int y, int m, int d); // проверка и инициализация даты
// ...
private:
int y, m, d; // год, месяц, день
bool check; // если дата правильная, возвращает true
};
Мы поместили проверку корректности даты в отдельную функцию check
Date::Date(int yy, int mm, int dd)
:y(yy), m(mm), d(dd) // инициализация данных - членов класса
{
if (!check) throw Invalid; // проверка корректности
}
bool Date::check // возвращает true, если дата корректна
{
if (m<1 || 12
// ...
}
Имея это определение класса Date
void f(int x, int y)
try {
Date dxy(2009,x,y);
cout << dxy << '\n'; // объявление оператора << см. в разделе 9.8
dxy.add_day(2);
}
catch(Date::Invalid) {
error("invalid date"); // функция error определена
// в разделе 5.6.3
}
Теперь мы знаем, что оператор <<
add_day
всегда будут работать с корректными объектами класса Date
. До завершения разработки класса Date
, описанной в разделе 9.7, опишем некоторые свойства языка, которые потребуются нам для того, чтобы сделать это хорошо: перечисления и перегрузку операторов. 9.5. Перечисления
enum
enum Month {
jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
};
“Тело” перечисления — это просто список его элементов. Каждому элементу перечисления можно задать конкретное значение, как это сделано выше с элементом jan
Month
присваивает каждому месяцу последовательные значения, начиная с единицы. Это эквивалентно следующему коду:enum Month {
jan=1, feb=2, mar=3, apr=4, may=5, jun=6,
jul=7, aug=8, sep=9, oct=10, nov=11, dec=12
};
Однако это утомительно и открывает много возможностей для ошибок. Фактически мы сделали две опечатки, пока не получили правильный вариант; лучше все же предоставить компилятору делать простую, повторяющуюся, “механическую” работу. Компилятор такие задачи решает лучше, чем люди, и при этом не устает.
Если не инициализировать первый элемент перечисления, то счетчик начнет отсчет с нуля. Рассмотрим такой пример:
enum Day {
monday, tuesday, wednesday, thursday, friday, saturday, sunday
};
где monday==0
sunday==6
. На практике лучше всего выбирать начальное значение счетчика, равным нулю.Перечисление Month
Month m = feb;
m = 7; // ошибка: нельзя присвоить целое число перечислению
int n = m; // OK: целочисленной переменной можно присвоить
// значение Month
Month mm = Month(7); // преобразование типа int в тип Month
//(без проверки)