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

на главную

Жанры

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

Date sunday(2009,8,29); // инициализируем объект Sunday

// триадой (2009,8,29)

Функцию-член класса можно также определить в определении класса.

// простой класс Date (детали реализации будут рассмотрены позднее)

class Date {

public:

Date(int yy, int mm, int dd)

:y(yy), m(mm), d(dd)

{

// ...

}

void add_day(int n)

{

// ...

}

int month { return m; }

// ...

private:

int y, m, d; //
год, месяц, день

};

Во-первых, отметим, что теперь объявление класса стало больше и запутаннее. В данном примере код конструктора и функции

add_day
могут содержать десятки строк. Это в несколько раз увеличивает размер объявления класса и затрудняет поиск интерфейса среди деталей реализации. Итак, мы не рекомендуем определять большие функции в объявлении класса. Тем не менее посмотрите на определение функции
month
. Оно проще и короче, чем определение
Date::month
, размещенное за пределами объявления класса. Определения коротких и простых функций можно размещать в объявлении класса.

Обратите внимание на то, что функция

month
может обращаться к переменной m, даже несмотря на то, что переменная m определена позже (ниже) функции
month
. Член класса может ссылаться на другой член класса независимо от того, в каком месте класса он определен. Правило, утверждающее, что имя переменной должно быть объявлено до ее использования, внутри класса ослабляется.

Определение функции-члена в классе приводит к следующим последствиям.

• Функция становится подставляемой (inlined), т.е. компилятор попытается сгенерировать код подставляемой функции вместо ее вызова. Это может дать значительное преимущество часто вызываемым функциям, таким как

month
.

• При изменении тела подставляемой функции-члена класса придется скомпилировать заново все модули, в которых он используется. Если тело функции определено за пределами объявления класса, то потребуется перекомпилировать только само определение класса. Отсутствие необходимости повторного компилирования при изменении тела функции может оказаться огромным преимуществом в больших программах.

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

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. Сообщения об ошибках

Что делать при обнаружении некорректной даты? В каком месте кода происходит поиск некорректных дат? В разделе 5.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) // инициализация данных - членов класса

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

На границе тучи ходят хмуро...

Кулаков Алексей Иванович
1. Александр Агренев
Фантастика:
альтернативная история
9.28
рейтинг книги
На границе тучи ходят хмуро...

Энфис. Книга 1

Кронос Александр
1. Эрра
Фантастика:
боевая фантастика
рпг
5.70
рейтинг книги
Энфис. Книга 1

Я – Орк. Том 4

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

Совок-8

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

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

Жена со скидкой, или Случайный брак

Ардова Алиса
Любовные романы:
любовно-фантастические романы
8.15
рейтинг книги
Жена со скидкой, или Случайный брак

Адепт: Обучение. Каникулы [СИ]

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.15
рейтинг книги
Адепт: Обучение. Каникулы [СИ]

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

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

Как я строил магическую империю 2

Зубов Константин
2. Как я строил магическую империю
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Как я строил магическую империю 2

Цеховик. Книга 1. Отрицание

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

Безымянный раб

Зыков Виталий Валерьевич
1. Дорога домой
Фантастика:
фэнтези
9.31
рейтинг книги
Безымянный раб

Матабар. II

Клеванский Кирилл Сергеевич
2. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар. II

Виконт. Книга 2. Обретение силы

Юллем Евгений
2. Псевдоним `Испанец`
Фантастика:
боевая фантастика
попаданцы
рпг
7.10
рейтинг книги
Виконт. Книга 2. Обретение силы

Первый пользователь. Книга 3

Сластин Артем
3. Первый пользователь
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Первый пользователь. Книга 3