Чтение онлайн

на главную

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

// простой класс Date (использует тип Month)

class Date {

public:

enum Month {

jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec

};

Date(int y, Month m, int d); // проверка даты и инициализация

// ...

private:

int y; // год

Month m;

int d; // день

};

Когда

мы используем тип
Month
, компилятор выдаст ошибку, если мы поменяем местами месяц и день. Кроме того, перечисление
Month
позволяет использовать символические имена. Такие имена, как правило, легче читать и записывать, чем работать с числами, подвергаясь риску ошибиться.

Date dx1(1998, 4, 3); // ошибка: 2-й аргумент не имеет

// тип Month

Date dx2(1998, 4, Date::mar); // ошибка: 2-й аргумент не имеет

// тип Month

Date dx2(4, Date::mar, 1998); // Ой: ошибка на этапе выполнения:

// день 1998

Date dx2(Date::mar, 4, 1998); // ошибка: 2-й аргумент не имеет

// тип Month

Date dx3(1998, Date::mar, 30); // OK

Этот код решает много проблем. Обратите внимание на квалификатор

Date
перечисления
mar: Date::mar
. Тем самым мы указываем, что это перечисление
mar
из класса
Date
. Это не эквивалентно обозначению
Date.mar
, поскольку
Date
— это не объект, а тип, а
mar
— не член класса, а символическая константа из перечисления, объявленного в классе. Обозначение
::
используется после имени класса (или пространства имен; см. раздел 8.7), а
.
(точка) — после имени объекта.

Когда есть выбор, ошибки следует выявлять на этапе компиляции, а не на этапе выполнения программы. Мы предпочитаем, чтобы ошибки вылавливал компилятор, а не искать, в каком месте кода возникла ошибка. Кроме того, для выявления ошибок на этапе компиляции не требуется писать и выполнять специальный код для проверки.

А нельзя ли подобным образом выявить путаницу между днем месяца и годом? Можно, но решение этой проблемы будет не таким элегантным, как для типа

Month;
помимо всего прочего, возможно, что мы имели в виду именно четвертый год. Даже если мы ограничимся современной эпохой, в перечисление придется включать слишком много лет.

Вероятно, было бы лучше всего (не вникая в предназначение класса Date) написать следующий код:

class Year { // год в диапазоне [min:max)

static const int min = 1800;

static const int max = 2200;

public:

class Invalid { };

Year(int x) : y(x) { if (x<min || max<=x) throw Invalid; }

int year { return y; }

private:

int y;

};

class Date {

public:

enum Month {

jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec

};

Date(Year y, Month m, int d); //
проверка даты и инициализация

// ...

private:

Year y;

Month m;

int d; // день

};

Теперь получаем фрагмент кода.

Date dx1(Year(1998),4,3); // ошибка: 2-й аргумент — не Month

Date dx2(Year(1998),4,Date::mar); // ошибка: 2-й аргумент — не Month

Date dx2(4, Date::mar,Year(1998)); // ошибка: 1-й аргумент — не Year

Date dx2(Date::mar,4,Year(1998)); // ошибка: 2-й аргумент — не Month

Date dx3(Year(1998),Date::mar,30); // OK

Следующая фатальная и неожиданная ошибка выявится только на этапе выполнения программы.

Date dx2(Year(4),Date::mar,1998); // ошибка на этапе выполнения:

// Year::Invalid

Стоило ли выполнять дополнительную работу и вводить обозначения для лет? Естественно, это зависит от того, какие задачи вы собираетесь решать с помощью типа Date, но в данном случае мы сомневаемся в этом и не хотели бы создавать отдельный класс

Year
.

Когда мы программируем, то всегда устанавливаем критерии качества для данного приложения. Как правило, мы не можем позволить себе роскошь очень долго искать идеальное решение, если уже нашли достаточно хорошее. Втягиваясь в поиски наилучшего решения, мы настолько запутаем программу, что она станет хуже, чем первоначальный вариант. Как сказал Вольтер: “Лучшее — враг хорошего”.

Обратите внимание на слова

static const
в определениях переменных
min
и
max
. Они позволяют нам определить символические константы для целых типов в классах. Использование модификатора
static
по отношению к члену класса гарантирует, что в программе существует только одна копия его значения, а не по одной копии на каждый объект данного класса.

9.7.2. Копирование

Мы всегда должны создавать объекты, иначе говоря, всегда предусматривать инициализацию и конструкторы. Вероятно, это самые важные члены класса: для того чтобы написать их, необходимо решить, как инициализировать объект и что значит корректность его значений (т.е. определить инвариант). Уже даже размышления об инициализации помогут вам избежать ошибок.

Затем необходимо решить, можно ли копировать объекты и как это делать? Для класса

Date
или перечисления
Month
ответ очевиден: копирование необходимо, и его смысл тривиален: просто копируются все члены класса. Фактически это предусмотрено по умолчанию. Если не указано ничего другого, компьютер сделает именно это. Например, если перечисление
Date
используется для инициализации или стоит в правой части оператора присваивания, то все его члены будут скопированы.

Поделиться:
Популярные книги

Кодекс Крови. Книга Х

Борзых М.
10. РОС: Кодекс Крови
Фантастика:
фэнтези
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга Х

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Защитник. Второй пояс

Игнатов Михаил Павлович
10. Путь
Фантастика:
фэнтези
5.25
рейтинг книги
Защитник. Второй пояс

Счастье быть нужным

Арниева Юлия
Любовные романы:
любовно-фантастические романы
5.25
рейтинг книги
Счастье быть нужным

Огненный князь 3

Машуков Тимур
3. Багряный восход
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Огненный князь 3

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

Не грози Дубровскому! Том III

Панарин Антон
3. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том III

Не отпускаю

Шагаева Наталья
Любовные романы:
современные любовные романы
эро литература
8.44
рейтинг книги
Не отпускаю

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Приручитель женщин-монстров. Том 4

Дорничев Дмитрий
4. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 4

Кодекс Охотника. Книга XVIII

Винокуров Юрий
18. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVIII

Польская партия

Ланцов Михаил Алексеевич
3. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Польская партия

Курсант: Назад в СССР 7

Дамиров Рафаэль
7. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 7

Белые погоны

Лисина Александра
3. Гибрид
Фантастика:
фэнтези
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Белые погоны