Конструктор из timel.cpp (рис. 6.5) присваивает нулевые (т.е. соответствующие 12 часам по полуночи в военном формате времени) начальные значения переменным hour, minute и second. Конструктор может содержать значения аргументов по умолчанию. Программа на рис. 6.8 переопределяет функцию конструктор Time так, чтобы она включала нулевые значения аргументов по умолчанию для каждой переменной. Задание в конструкторе аргументов по умолчанию позволяет гарантировать, что объект будет находиться в непротиворечивом состоянии, даже если в вызове конструктора не указаны никакие значения. Созданный программистом конструктор, у которого все аргументы — аргументы по умолчанию (или который не требует никаких аргументов), называется конструктором с умолчанием, т.е. конструктором, который можно вызывать без указания каких-либо аргументов.
// TIME2.H // Объявление класса Time.
// Функции-элементы определенны в TIME.CPP,
// предотвращение неоднократного включения заголовочного файла fifndef Т1МЕ2_Н #define Т1МЕ2_Н
class Time { public:
V ■4 * |
Time(int = 0, int = 0, int = 0); //конструктор с умолчанием void setTime(int, int, int); void printMilitary(); ^ * void printStandard(); private:
int hour; int minute; int second;
} ;
lendif
Рис. 6.8. Использование конструктора с аргументами по умолчанию (часть 1 из 4) // Т1МЕ2.СРР
t |
^ [ // Определения функций-элементов класса Time #include <iostream.h> #include "time2.h"
П |
// Функция конструктор для задания начальных значений закрытых данных.
// По умолчанию значения равны 0 (смотри определение класса) . Time::Time(int hr, int min, int sec) { setTime(hr, min, sec); }
// Установка значений hour, minute и second. // Неверные значения устанавливаются равными 0.
V |
$ void Time::setTime(int h, int m, int s) * ! {
hour = (h >= 0 && h < 24) ? h : 0; minute = (m >= 0 && m < 60) ? m : 0; second = (s >= 0 && s < 60) ?s:0;
* H |
}
//Отображение времени в военном формате: HH:MM:SS
void Time:: printMilitary ( ) {
cout « (hour < 10 ? "0" : "") « hour << ":" « (minute < 10 ? "0" : "") « minute « « (second < 10 ? "0" : "") « second;}
// Отображение времени в стандартном формате: HH:MM:SS AM (или РМ)
void Time:-.printStandard () {
"") « second ) ; |
cout « ((hour == 0 || hour == 12) ? 12 : hour %12) « ":"« (minute < 10 ? "0" : "") « minute « ":"« (second < 10 ? "0" : « (hour < 12 ? " AM" : " PM
Для каждого класса может существовать только один конструктор с умолчанием. В этой программе конструктор вызывает функцию-элемент setTime со значениями, передаваемыми конструктору (или значениями по умолчанию), чтобы гарантировать, что значение, предназначенное для hour, находится в диапазоне от 0 до 23, а значения для minute и second — в диапазоне от 0 до 59. Если значение выходит за пределы диапазона, оно устанавливается равным нулю с помощью setTime (это пример гарантии того, что данные- элементы будут в непротиворечивом состоянии).
// FIG6_8.CPP
// Демонстрация функции конструктора с умолчанием // для класса Time, iinclude <iostream.h> iinclude "time2.h"
main() {
Time tl, t2{2), t3(21, 34), t4 (12, 25, 42), t5 (27, 74, 99);
cout << "Варианты:" << endl
« "все аргументы по умолчанию:" « endl « " "; tl.printMilitary(); cout « endl « " "; tl.printStandard() ;
cout « endl « "часы заданы; минуты и секунды по умолчанию:"
« endl« " " ; t2.printMilitary(); cout « endl « " " ; t2.printStandard();
cout << endl << "часы и минуты заданы; секунды по умолчанию:"
« endl« " " ; t3.printMilitary() ; cout « endl « " "; t3.printStandard();
cout << endl << "часы, минуты и секунды заданы:"
« endl« " "; t4.printMilitary(); cout « endl « " "; t4.printStandard();
cout « endl « "все значения заданы неверно:"
« endl« " " ; t5.printMilitary(); cout « endl « " "; t5.printStandard();
return 0; }
Варианты:
все аргументы по умолчанию: 00:00:00 12:00:00 AM часы заданы; минуты и секунды по умолчанию: 02:00:00 2:00:00 AM
часы и минуты заданы; секунды по умолчанию: 21:34:00 9:34:00 РМ часы, минуты и секунды заданы: 12:25:42 12:25:42 РМ все значения заданы неверно: 00:00:00 12:00:00 AM
Рис. 6.8. Использование конструктора с аргументами по умолчанию (часть 4 из 4)
Заметим, что конструктор Time мог бы быть написан с включением тех же самых операторов, что имеются в функции-элементе setTime. Это могло бы быть несколько более эффективным, потому что исключается лишний вызов setTime. Однако, одинаковые коды в конструкторе Time и в функ- ции-элементе setTime затруднят сопровождение этой программы. Если реализация функции-элемента setTime изменится, соответствующие изменения надо будет вносить и в реализацию конструктора Time. То, что конструктор Time непосредственно вызывает setTime, позволяет делать любые изменения только в реализации setTime. Это уменьшает вероятность ошибки программирования при изменениях в реализации. Кроме того, эффективность конструктора Time может быть увеличена путем явного объявления конструктора inline или путем описания конструктора в определении класса (это означает неявное определение функции как inline).
Замечание по технике программирования 6.16
Если функция-элемент класса уже обеспечивает все или часть функциональных возможностей, требуемых конструктором (или другой функцией-элементом), вызывайте эту функцию-элемент из конструктора (или другой функции-элемента). Это упрощает сопровождение программы и уменьшает вероятность ошибки при изменении реализации кода.
Хороший стиль программирования 6.9
Объявляйте аргументы функции по умолчанию только в прототипе функции внутри определения класса в заголовочном файле.
Типичная ошибка программирования 6.6
Указание начальных значений по умолчанию для одной и той же функции-элемента как в заголовочном файле, так и в описании функции-элемента.
Программа на рис. 6.8 создает 5 экземпляров объектов Time и задает им начальные значения: одному — со всеми тремя аргументами по умолчанию в вызове конструктора, второму — с одним указанным аргументам, третье- му — с двумя указанными аргументами, четвертому — с тремя указанными аргументами и пятому — с тремя неверно указанными аргументами. Отображается содержание данных каждого объекта после его создания и задания начальных значений.
Если для класса не определено никакого конструктора, компилятор создает конструктор с умолчанием. Такой конструктор не задает никаких начальных значений, так что после создания объекта нет никакой гарантии, что он находится в непротиворечивом состоянии.
Комментариев нет:
Отправить комментарий