Было также внесено еще одно изменение: в начале определения класса использовано ключевое слово class
, а не struct
. Это изменение является чисто стилистическим; тип класса можно определить при помощи любого из этих ключевых слов. Единственное различие между ключевыми словами struct
и class
в заданном по умолчанию уровне доступа.
Члены класса могут быть определены перед первым спецификатором доступа. Уровень доступа к таким членам будет зависеть от того, как определяется класс. Если используется ключевое слово struct
, то члены, определенные до первого спецификатора доступа, будут открытыми; если используется ключевое слово class
, то они будут закрытыми.
Общепринятым стилем считается определение классов, все члены которого предположительно будут открытыми, с использованием ключевого слова struct
. Если члены класса должны быть закрытыми, используется ключевое слово class
.
class
и struct
в задаваемом по умолчанию уровне доступа.
Инкапсуляция предоставляет два важных преимущества.
• Пользовательский код не может по неосторожности повредить состояние инкапсулированного объекта.
• Реализация инкапсулированного класса может со временем измениться, это не потребует изменений в коде на пользовательском уровне.
Определив переменные-члены закрытыми, автор класса получает возможность вносить изменения в данные. Если реализация изменится, то вызванные этим последствия можно исследовать только в коде класса. Пользовательский код придется изменять только при изменении интерфейса. Если данные являются открытыми, то любой использовавший их код может быть нарушен. Пришлось бы найти и переписать любой код, который полагался на прежнюю реализацию, и только затем использовать программу.
Еще одно преимущество объявления переменных-членов закрытыми в том, что данные защищены от ошибок, которые могли бы внести пользователи. Если есть ошибка, повреждающая состояние объекта, места ее поиска ограничены только тем кодом, который является частью реализации. Это существенно облегчает поиск проблем и обслуживание программы.
Упражнение 7.16. Каковы ограничения (если они есть) на количество спецификаторов доступа в определении класса? Какие виды членов должны быть определены после спецификатора public
? Какие после спецификатора private
?
Упражнение 7.17. Каковы различия (если они есть) между ключевыми словами class
и struct
?
Упражнение 7.18. Что такое инкапсуляция? Чем она полезна?
Упражнение 7.19. Укажите, какие члены класса Person имеет смысл объявить как public
, а какие как private
. Объясните свой выбор.
Теперь, когда переменные-члены класса Sales_data
стали закрытыми, функции read()
, print()
и add()
перестали компилироваться. Проблема в том, что хоть эти функции и являются частью интерфейса класса Sales_data
, его членами они не являются.
Класс может позволить другому классу или функции получить доступ к своим не открытым членам, установив для них friend
:
class Sales_data {
//
//
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);