Урок 114. Спецификаторы доступа public и private

   ⁄ 

 Обновлено 10 Фев 2018  ⁄ 

 ⁄   4 

⁄   1350

Рассмотрим следующую программу:

Здесь мы объявляем структуру DateStruct, а затем напрямую обращаемся к её членам для их инициализации. Этот способ работает, так как все члены структуры являются открытыми по умолчанию. Члены public (открытые или публичные) – это члены структуры или класса, к которым можно получить доступ извне этой же структуры или класса. В программе выше функция main() находится вне структуры, но она может напрямую обращаться к членам day, month и year, так как они являются открытыми.

С другой стороны, рассмотрим следующий почти идентичный класс:

Вам бы не удалось скомпилировать эту программу, так как все члены класса являются закрытыми по умолчанию. Члены private (закрытые или частные) – это члены класса, доступ к которым возможен только другим членам класса. Поскольку функция main() не является членом DateClass, то она и не имеет доступа к закрытым членам объекта date.

Спецификаторы доступа

Хотя члены класса являются закрытыми по умолчанию, мы можем сделать их открытыми, используя ключевое слово public:

Поскольку теперь члены DateClass являются открытыми, то к ним можно получить доступ напрямую из функции main().

Ключевое слово public вместе с двоеточием называется спецификатором доступа. Спецификатор доступа определяет, кто имеет доступ к членам, которые следуют за спецификатором. Каждый из членов «приобретает» уровень доступа в соответствии со спецификатором доступа (или, если он не указан, в соответствии со спецификатором доступа по умолчанию).

В C++ есть 3 уровня доступа: public, private и protected. Public и private используются для членов, чтобы сделать их открытыми, либо закрытыми. Третий спецификатор доступа, protected (защищенный), работает почти так же, как и private. Детальнее о нем и его отличиях от private мы поговорим, когда будем рассматривать наследование.

Использование спецификаторов доступа

Классы могут использовать (и активно используют) сразу несколько спецификаторов доступа для установки уровней доступа каждого из своих членов.



Обычно переменные-члены являются закрытыми, а методы – открытыми. Почему именно так — мы поговорим в следующем уроке.

Правило: Устанавливайте спецификатор доступа private переменным-членам класса и спецификатор доступа public методам класса (если у вас нет веских оснований, чтобы делать иначе).

Рассмотрим пример класса, который использует как private, так и public спецификаторы доступа:

Результат выполнения программы выше:

12/11/2018

Обратите внимание, хоть мы и не можем получить доступ к переменным объекта date напрямую из main() (так как они являются private по умолчанию), мы можем получить доступ к ним через public методы setDate() и print()!

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

Некоторые программисты предпочитают сначала перечислять члены private, а затем уже public, так как члены public обычно используют члены private (те же переменные-члены в методах класса), поэтому имеет смысл сначала определять private, а затем уже public. Другие же программисты считают, что сначала нужно указывать члены public, так как члены private закрыты, получать к ним доступ напрямую нельзя, то и выносить их на первое место не нужно. Работать будет и так, и так. Какой способ использовать – выбирайте сами, как вам удобнее.

Контроль доступа работает на основе класса

Рассмотрим следующую программу:

Один нюанс в C++, который часто игнорируют, забывают или неправильно понимают, заключается в том, что контроль доступа работает на основе класса, а не на основе объекта. Это означает, что когда метод имеет доступ к закрытыми членам класса, то он может обращаться к закрытым членам любого объекта этого типа класса (которые только есть).

В примере выше функция copyFrom() является членом класса DateClass, что дает ей доступ к private членам DateClass. Это означает, что copyFrom() может не только напрямую обращаться к закрытым членам неявного объекта, с которым работает (копия объекта), но и имеет прямой доступ к закрытым членам объекта b класса DateClass!

Это полезно, когда нужно скопировать элементы из одного объекта класса в другой объект того же класса. Детальнее об этом мы поговорим в следующих уроках.

Структуры vs Классы

Теперь, когда мы узнали о спецификаторах доступа, мы можем говорить о фактических различиях между классом и структурой в C++. Класс, по умолчанию, устанавливает всем своим членам спецификатор доступа private. Структура же, по умолчанию, устанавливает всем своим членам спецификатор доступа public.

Вот так вот!

(Есть еще одно незначительное отличие — структуры наследуют от других классов открыто, а классы наследуют закрыто. Мы рассмотрим, что всё это значит в следующей главе).



Тест

Задание №1

a) Что такое открытый член?

Ответ а)

Открытый член — это член класса, доступ к которому может быть осуществлен кем-угодно.

b) Что такое закрытый член?

Ответ b)

Закрытый член — это член класса, доступ к которому разрешен только другим членам класса.

c) Что такое спецификатор доступа?

Ответ c)

Спецификатор доступа определяет, кто имеет доступ к членам, которые следуют за спецификатором.

d) Сколько есть спецификаторов доступа, назовите их?

Ответ d)

3. Public, private и protected.

Задание №2

a) Напишите простой класс с именем Numbers. Этот класс должен иметь:

  три private переменные-члены типа double: m_a, m_b и m_c;

  public метод с именем setValues(), который позволит устанавливать значения для m_a, m_b и m_c;

  public метод с именем print(), который будет выводить объект класса Numbers в формате: <m_a, m_b, m_c>.

Следующий код main():

должен производить следующий результат:

<3, 4, 5>

Ответ а)

b) Добавьте функцию isEqual() в класс Numbers, чтобы следующий код работал корректно:

Ответ b)

Задание №3

a) Теперь попробуем что-то сложнее. Напишите класс, который реализует функциональность стека. Что такое стек — смотрите урок 105.

Класс Stack должен иметь:

  private фиксированный массив целых чисел длиной 10;

  private целочисленное значение для отслеживания длины стека;

  public метод с именем reset(), который будет сбрасывать длину и все значения элементов на 0;

  public метод с именем push(), который будет добавлять значение в стек. push() должен возвращать значение false, если массив уже заполнен, и true в противном случае;

  public метод с именем pop() для вытягивания и возврата значения из стека. Если в стеке нет значений, то должен выводиться стейтмент assert;

  public метод с именем print(), который будет выводить все значения стека.

Следующий код main():

должен производить следующий результат:

( )
( 3 7 5 )
( 3 7 )
( )

Ответ a)

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (10 оценок, среднее: 5,00 из 5)
Загрузка...
Подписаться на обновления:

Комментариев: 4

  1. Sergey:

    И ещё возник вопрос, правильно ли у меня работает assert hello-site.ru/share/Stek — код программы. priscree.ru/img/ddd58dea7702d7.jpg — скриншот проблемы. Приходится закрывать всплывающее окно, не похоже на нормальную работу программы…

    1. Li4ik:

      У вас код идентичен с кодом ответа (только другие имена переменных). Всё правильно. Появление ошибки — это нормальное срабатывание стейтмента assert. Assert у вас срабатывает, так как вы вызываете метод pop, прежде чем заполняете стек данными:

      Это бессмысленно. Вы пытаетесь вытянуть элемент из пустого стека. Соответственно, срабатывает assert, который и прописан для такого случая.

  2. Sergey:

    Есть небольшая недоработка в ответе задания 3, в разделе private класса Stack, нужно инициализировать индекс свободного элемента стека в 0. (На случай, если кто-то сразу захочет вызвать метод pop)

    1. Li4ik:

      Так ведь используется стейтмент assert, который выведет сообщение об ошибке, если кто-то попытается вызвать метод pop сразу. Зачем инициализировать нулём?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

ПОДПИСЫВАЙТЕСЬ

НА КАНАЛ RAVESLI В TELEGRAM

@ravesli

ПОДПИСАТЬСЯ БЕСПЛАТНО