"Информатика (базовый и углублённый уровни) (в 2 частях)", Поляков К.Ю., Еремин Е.А.
Модификаторы определяют, кто и каким образом может обращаться к полям и методам класса. С их помощью внутренние данные скрывают от внешнего кода, а для работы с объектом оставляют понятные открытые методы. В C++ уровни доступа задают ключевые слова public, private и protected; метка действует до следующей метки. Отдельно используется static: он показывает, что поле или метод относится ко всему классу, а не к одному объекту.
Текст подготовлен нейронной сетью по теме параграфа и не заменяет учебник — важные факты и формулировки сверяйте с ним.
Модификатор доступа — ключевое слово, задающее, из каких частей программы доступен член класса. Оно помогает отделить то, чем можно пользоваться снаружи, от деталей реализации. Благодаря этому пользователь класса не зависит от того, как именно хранятся и обрабатываются данные.
public — модификатор, разрешающий обращаться к членам класса извне. Открытые поля и методы можно использовать в главной программе и в коде, который работает с объектом. Через public обычно предоставляют понятные операции, нужные пользователю класса.
private — модификатор, ограничивающий доступ к членам класса самим классом и его методами. Внешний код не может напрямую читать или менять такие данные, зато методы класса могут контролировать их использование. Это нужно, чтобы состояние объекта не нарушалось случайными действиями.
protected — модификатор, разрешающий доступ внутри класса и его наследников. Наследник — класс, созданный на основе другого класса; ему иногда нужно использовать общие данные или операции. При этом обычный внешний код к protected-членам напрямую не обращается.
Класс может скрывать устройство своих данных, оставляя открытыми только способы работы с ними. Такой подход называют инкапсуляцией: внутренние детали отделяют от внешнего интерфейса, то есть доступных пользователю операций. Причина в том, что прямое изменение данных может привести к противоречивому состоянию объекта. Если изменение проходит через метод, метод может проверить значение и не допустить ошибки.
Разделить класс на открытые и закрытые части позволяют метки public, private и protected. Например, поле с внутренними данными можно объявить после private, а методы для работы с ним — после public. Тогда внешний код видит только предусмотренные создателем класса операции, а не все детали реализации. Protected выбирают, когда доступ к члену нужен не всем, а самому классу и его потомкам.
Доступность определяется одновременно уровнем доступа и местом, откуда обращаются к члену. Внешний код может обратиться к public-члену, но не к private; метод класса имеет доступ и к собственным private-членам. Метод производного класса может использовать protected-член базового класса, тогда как private-член базового класса ему недоступен напрямую. Поэтому перед обращением полезно выяснить и кто выполняет действие, и где объявлен нужный член.
В C++ метка доступа действует на все объявления после неё до следующей метки доступа или конца класса. Она не ограничивается только ближайшим полем или методом: если после public перечислены несколько членов, они все будут открытыми. Это позволяет группировать объявления по назначению и не повторять ключевое слово перед каждым из них. При чтении класса нужно проследить, какая метка стоит перед конкретным объявлением.
Ключевое слово static задаёт не уровень доступа, а принадлежность члена классу в целом. Обычное поле хранится отдельно у каждого объекта, а статическое поле одно на весь класс. Статический метод тоже не привязан к конкретному объекту и может напрямую работать со статическими членами. Если метод должен обратиться к нестатическому полю, ему нужен объект, потому что у класса в целом нет единственного значения такого поля.
| Модификатор | Доступ извне | Доступ в методах этого класса | Доступ в производном классе |
|---|---|---|---|
| public | Разрешён | Разрешён | Разрешён |
| private | Запрещён | Разрешён | Запрещён напрямую |
| protected | Запрещён | Разрешён | Разрешён |
Чтобы воспользоваться таблицей, сначала определите, откуда идёт обращение: извне, из метода самого класса или из производного класса. Затем найдите строку нужного модификатора и проверьте соответствующий столбец. Таблица показывает правила доступа, но не отменяет необходимости проверить, действительно ли член объявлен под указанной меткой.
Условие. В классе объявлены открытое поле x и закрытое поле y. Определить, к каким полям можно обратиться непосредственно из главной программы. Проверим именно прямое обращение, без вызова методов.
Ответ: непосредственно доступно поле x; к y нужно обращаться через открытый метод класса, если такой метод предусмотрен.
Условие. В программе поле с данными изменяют напрямую из главной программы, а затем требуется вывести его значение через метод. Исправим класс так, чтобы изменение происходило контролируемо, а вывод выполнялся через его интерфейс.
Ответ: поле закрыто, а изменение и чтение организованы через public-методы. Так класс сохраняет контроль над своими данными.
Условие. Требуется создать класс с закрытым полем-счётчиком объектов и статическим методом, который возвращает число созданных объектов. Счётчик должен быть общим, а не отдельным для каждого экземпляра.
Ответ: счётчик хранится в одном статическом поле, а статический метод предоставляет к нему контролируемый доступ. Само поле остаётся закрытым.
Ошибочно считать, что private запрещает доступ даже методам самого класса. Такое заблуждение возникает из-за слова «закрытый», которое принимают за запрет для всех. Проверьте, откуда выполняется обращение: собственные методы класса могут использовать его private-члены, внешний код — нет.
Попытка обратиться к private-члену напрямую из главной программы нарушает правила доступа. Часто так происходит, когда забывают, что объект не делает закрытые поля открытыми. Перед записью обращения проверьте метку над объявлением; если там private, используйте предусмотренный public-метод.
Метка доступа в C++ относится не только к следующему объявлению, а действует до следующей метки. Ошибка появляется, если читать список членов так, будто каждому из них нужна отдельная пометка. Для самопроверки найдите ближайшую предыдущую метку public, private или protected и проследите, не встретилась ли другая.
Считать static модификатором доступа — значит путать два разных свойства члена. Public, private и protected отвечают на вопрос, кто может обратиться, а static — относится ли член к объекту или ко всему классу. Проверяйте эти свойства отдельно: член может быть, например, private static или public static.
Чтобы разобраться с модификаторами, нужно знать, как объявляются классы, объекты, поля и методы. Поле хранит данные, метод задаёт действие, а объект является конкретным экземпляром класса. Понимание этих понятий помогает определить, к какому члену относится обращение и из какой части программы оно выполняется.
Модификаторы связаны с инкапсуляцией и наследованием. Инкапсуляция помогает задать интерфейс класса и защитить его данные, а при наследовании уровни доступа определяют, какие члены сможет использовать производный класс. Поэтому выбор между private и protected влияет не только на внешний код, но и на возможность расширять класс.
Чем public отличается от private?
Члены public доступны коду вне класса, например главной программе. К членам private могут обращаться методы самого класса, но не внешний код напрямую.
Могут ли методы класса обращаться к его private-полям?
Да, методы класса имеют доступ к его private-полям. Благодаря этому они могут проверять и изменять данные по заданным правилам.
Что произойдёт, если обратиться к private-полю из главной программы?
Компилятор сообщит об ошибке доступа. Чтобы получить или изменить значение, нужно вызвать открытый метод, предусмотренный классом.
Как protected отличается от private?
Оба уровня закрывают член от обычного внешнего кода. Однако protected-член, помимо методов своего класса, доступен методам производных классов.
Чем статическое поле отличается от обычного поля объекта?
Обычное поле хранится отдельно в каждом объекте. Статическое поле общее для всего класса, поэтому его значение не дублируется при создании новых объектов.
§ 69. Модификаторы