Шрифт:
9.4.5. Ссылка на текущий объект
Рассмотрим простой пример использования класса
Date
.
class Date {
// ...
int month { return m; }
// ...
private:
int y, m, d; // год, месяц, день
};
void f(Date d1, Date d2)
{
cout << d1.month << ' ' << d2.month << '\n';
}
Откуда функции
Date::month
известно, что при первом вызове следует вернуть значение переменной d1.m
, а при втором — d2.m
? Посмотрите на функцию Date::month
еще раз; ее объявление не имеет аргумента! Как функция Date::month
“узнает”, для какого объекта она вызывается? Функции-члены класса, такие как Date::month
, имеют неявный аргумент, позволяющий идентифицировать объект, для которого они вызываются. Итак, при первом вызове переменная m правильно ссылается на d1.m
, а при втором — на d2.m
. Другие варианты использования неявного аргумента описаны в разделе 17.10. 9.4.6. Сообщения об ошибках
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<m) return false;
// ...
}
Имея это определение класса
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, опишем некоторые свойства языка, которые потребуются нам для того, чтобы сделать это хорошо: перечисления и перегрузку операторов.