Внимательный читатель заметил, что мы ни в одном из примеров не объявляли констант. Более того, при рассказе о передаче параметров в функции не было ни одного примера с передачей параметра по константной ссылке. Это не случайно: попытки вывода константы на экран посредством метода DisplayMoney () вызывают ошибки компиляции! Разберемся в этом вопросе подробнее. На работе вам может понадобится изменение голоса, которое можно сделать тут что бы вас не узнали.
Конструкторы обеспечивают привычную форму объявления констант; все переменные, которые мы объявляли инициализированными, можно объявить константами, указав перед ними слово const, например:
const ТМопеу d2(100,67); const ТМопеу d0 = 100; const ТМопеу d5 = ТМопеу(100); const ТМопеу d3(d2);
Как видим, это фактически совпадает с объявлением констант встроенных типов. Однако вывести константу на экран не удается! Например: d2 .DisplayMoneyO ;
Этот оператор вызывает ошибку трансляции С26621:
cannot convert 'this' pointer from 'const TMoney' to 'TMoney &'
Это сообщение говорит о невозможности преобразовать указатель this из типа const ТМопеу в тип ТМопеу &.
Для вывода констант на экран надо объявить константный метод (см. п. п. 9.3.1/3 в [1]). Константный метод — это не метод, возвращающий константу в качестве результата, а метод, который можно вызвать для объекта-константы «своего» класса. Объявление константного метода делается просто: надо указать слово const в заголовке функции после списка параметров, но перед телом, например:
class Т
{ Т f(void);
Т f(void) const;
// неконстантный метод // константный метод
Константные и неконстантные методы не являются эквивалентными, даже если у них,полностью совпадают прототипы (кроме слова const после списка параметров). В классе можно иметь и константный, и неконстантный метод с одинаковым прототипом, так как константный метод отличается по типу от аналогичного неконстантного метода.
Кандидатами в константные методы являются методы, не изменяющие состояние объекта, то есть не присваивающие новых значений полям класса. Компилятор следит за этим, поэтому при обнаружении явных операторов изменения полей (присваивание и ввод значений) немедленно выдает сообщение об ошибке. Конечно, компилятор, как всегда, можно «обмануть» разными способами (например, за счет косвенного доступа по указателю), но не стоит этого делать — зачем тогда объявлять метод константным?
Константные методы могут работать как с константными объектами, так и с обычными объектами-переменными. Поэтому при разработке классов нужно определить, какие методы не будут изменять состояние полей класса, и сделать эти методы константными. В нашем случае это, очевидно, метод DisplayMoneyO. Однако он использует приватную неконстантную функцию toStringO, поэтому сделать его константным, просто указав ключевое слово const в заголовке, не получится — надо делать константной и функцию toStringO. Таким образом, прототипы (и заголовки) этих методов будут такими:
string toStringO const; void DisplayMoneyO const;
После этого на экран выводятся и константы, и переменные. Теперь мы можем использовать этот метод в функции, которой параметр передается по константной ссылке. Изменим прототип показанной ранее функции f 1()(см. листинг 2.5):
TMoney fl(const ТМопеу &t);
Однако теперь протесты компилятора вызывает оператор t = t.AddMoneyO.0);
И это естественно, так как константе нельзя присваивать значение. Изменим нашу функцию так:
TMoney fl(const ТМопеу &t = f1(100)) // вызов определяемой функции { cout << ит"1="; t .DisplayMoneyO ; ТМопеу г = t; г = г.AddMoney(1.0);
return г;
}
Теперь все работает точно так же, как и в приведенном ранее примере.
Собственно, все методы класса TMoney, кроме Init() и Read(), можно сделать константными, так как они не изменяют поля текущего объекта. |