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

на главную

Жанры

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

Ключевое слово

const
в объявлении функции-члена стоит сразу после списка аргументов, чтобы обозначить, что эту функцию-член можно вызывать для константных объектов. Как только мы объявили функцию-член константной, компилятор берет с нас обещание не модифицировать объект. Рассмотрим пример.

int Date::day const

{

++d; // ошибка: попытка изменить объект в константной

// функции - члене

return d;

}

Естественно, как правило, мы не собираемся мошенничать. В основном компилятор

обеспечивает защиту от несчастных случаев, что очень полезно при разработке сложных программ.

9.7.5. Члены и вспомогательные функции

Разрабатывая минимальный (хотя и полный) интерфейс, мы вынуждены оставлять за бортом много полезных операций. Функцию, которая могла бы быть просто, элегантно и эффективно реализована как самостоятельная функция (т.е. не функция-член), следует реализовать за пределами класса. Таким образом, функция не сможет повредить данные, хранящиеся в объекте класса. Предотвращение доступа к данным является важным фактором, поскольку обычные методы поиска ошибок “вращаются вокруг типичных подозрительных мест”; иначе говоря, если с классом что-то не так, мы в первую очередь проверяем функции, имеющие прямой доступ к его представлению: одна из них обязательно является причиной ошибки. Если таких функций десяток, нам будет намного проще работать, чем если их будет пятьдесят.

Пятьдесят функций для класса

Date
! Возможно, вы думаете, что мы шутим. Вовсе нет: несколько лет назад я делал обзор нескольких коммерческих библиотек для работы с календарем и обнаружил в них множество функций вроде
next_Sunday
,
next_workday
и т.д. Пятьдесят — это совсем не невероятное число для класса, разработанного для удобства пользователей, а не для удобства его проектирования, реализации и сопровождения.

Отметим также, что если представление изменяется, то переписать достаточно только функции, которые имеют к ней прямой доступ. Это вторая важная практическая причина для минимизации интерфейса. Разрабатывая класс

Date
, мы могли решить, что дату лучше представлять в виде целого числа дней, прошедших с 1 января 1900 года, а не в виде тройки (год, месяц, день). В этом случае нам придется изменить только функции-члены.

Рассмотрим несколько примеров вспомогательных функций (helper functions).

Date next_Sunday(const Date& d)

{

// имеет доступ к объекту d, используя d.day, d.month

// и d.year

// создает и возвращает новый объект класса Date

}

Date next_weekday(const Date& d) { /* ... */ }

bool leapyear(int y) { /* ... */ }

bool operator==(const Date& a, const Date& b)

{

return a.year==b.year

&& a.month==b.month

&& a.day==b.day;

}

bool operator!=(const Date& a, const Date& b)

{

return !(a==b);

}

Вспомогательные функции также называют функциями-помощниками. Различие между этими и другими функциями, не являющимися членами класса, заключается в логике работы; иначе говоря, вспомогательная функция представляет собой концепцию
проектирования, а не концепцию языка программирования. Вспомогательная функция часто получает в качестве аргументов объекты класса, для которого они играют вспомогательную роль. Хотя существуют исключения, например функция
leapyear
. Часто для идентификации вспомогательных функций используются пространства имен (см. раздел 8.7).

namespace Chrono {

class Date { /* ... */ };

bool is_date(int y, Date::Month m, int d); // true для

// корректных данных

Date next_Sunday(const Date& d) { /* ... */ }

Date next_weekday(const Date& d) { /* ... */ }

bool leapyear(int y) { /* ... */ } // см. пример 10

bool operator==(const Date& a, const Date& b) { /* ... */ }

// ...

}

Обратите внимание на функции

==
и
!=
. Это типичные вспомогательные функции. Для многих классов функции
==
и
!=
имеют очевидный смысл, но, поскольку это не распространяется на все классы, компилятор не может создать их вместо программиста, как копирующий конструктор или копирующее присваивание.

Отметьте также, что мы ввели вспомогательную функцию

is_date
, которая заменяет функцию
Date::check
, поскольку проверка корректности даты во многом не зависит от представления класса
Date
. Например, нам не нужно знать, как представлены объекты класса
Date
для того, чтобы узнать, что дата “30 января 2008 года” является корректной, а “30 февраля 2008 года” — нет. Возможно, существуют аспекты даты, которые зависят от ее представления (например, корректна ли дата “30 января 1066 года”), но (при необходимости) конструктор
Date
может позаботиться и об этом.

9.8. Класс Date

Итак, соединим все идеи и понятия вместе и посмотрим, как будет выглядеть класс

Date
. Там, где тело функции содержит лишь комментарий
...
, фактическая реализация слишком сложна (пожалуйста, не пытайтесь пока ее написать). Сначала разместим объявления в заголовочном файле
Chrono.h
.

// файл Chrono.h

#include "Chrono.h"

namespace Chrono {

class Date {

public:

enum Month {

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

};

class Invalid { }; // для генерации в виде исключения

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

Date; // конструктор по умолчанию

// операции копирования по умолчанию

// в порядке

// немодифицирующие операции:

int day const { return d; }

Month month const { return m; }

int year const { return y; }

// модифицирующие операции:

void add_day(int n);

void add_month(int n);

void add_year(int n);

private:

int y;

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

Мир-о-творец

Ланцов Михаил Алексеевич
8. Помещик
Фантастика:
альтернативная история
5.00
рейтинг книги
Мир-о-творец

Виконт. Книга 4. Колонист

Юллем Евгений
Псевдоним `Испанец`
Фантастика:
фэнтези
попаданцы
аниме
7.50
рейтинг книги
Виконт. Книга 4. Колонист

Титан империи

Артемов Александр Александрович
1. Титан Империи
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Титан империи

Запретный Мир

Каменистый Артем
1. Запретный Мир
Фантастика:
фэнтези
героическая фантастика
8.94
рейтинг книги
Запретный Мир

Ты предал нашу семью

Рей Полина
2. Предатели
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Ты предал нашу семью

Цеховик. Книга 2. Движение к цели

Ромов Дмитрий
2. Цеховик
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Цеховик. Книга 2. Движение к цели

Сила рода. Том 3

Вяч Павел
2. Претендент
Фантастика:
фэнтези
боевая фантастика
6.17
рейтинг книги
Сила рода. Том 3

Проданная невеста

Wolf Lita
Любовные романы:
любовно-фантастические романы
5.80
рейтинг книги
Проданная невеста

Волк 7: Лихие 90-е

Киров Никита
7. Волков
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Волк 7: Лихие 90-е

Падение Твердыни

Распопов Дмитрий Викторович
6. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Падение Твердыни

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

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

Ночь со зверем

Владимирова Анна
3. Оборотни-медведи
Любовные романы:
любовно-фантастические романы
5.25
рейтинг книги
Ночь со зверем

Я – Орк. Том 6

Лисицин Евгений
6. Я — Орк
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я – Орк. Том 6

Совок-8

Агарев Вадим
8. Совок
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Совок-8