Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Лафоре Р. -> "Объектно-ориентированное программирование в С++" -> 138

Объектно-ориентированное программирование в С++ - Лафоре Р.

Лафоре Р. Объектно-ориентированное программирование в С++ — М.: Питер, 2004. — 992 c.
Скачать (прямая ссылка): obektnoorentprogramm2004.djvu
Предыдущая << 1 .. 132 133 134 135 136 137 < 138 > 139 140 141 142 143 144 .. 341 >> Следующая


Доступ к базовому классу

Знание того, когда для объектов производного класса могут быть использованы методы базового класса, является важной темой в наследовании. Это называется правами доступа. Рассмотрим, как компилятор использует их в примере COUNTEN.

Подстановка конструкторов базового класса

Создадим объект класса CountDn в функции main():

CountOn cl:

Эта строка означает, что cl будет создан как объект класса CountDn и инициализирован нулем. Но в классе CountDn нет конструктора, каким же образом выполняется инициализация? Оказывается, что если мы не определили конструктор производного класса, то будет использоваться подходящий конструктор базового класса. В COUNTEN конструктор класса CountDn отсутствует, и компилятор использует конструктор класса Counter без аргументов.

Такая гибкость компилятора — использование доступного метода взамен отсутствующего — обычная ситуация, возникающая при наследовании.

Подстановка методов базового класса

Объект cl класса CountDn также может использовать методы operator++() и get_ coupt() из базового класса. Сначала используем увеличение cl:

++Cl: 366 Глава 9. Наследование

Затем выведем на экран значение счетчика cl: cout « "\n cl = " « cl.get_count ( ):

Вновь компилятор, не найдя этих методов в классе, объектом которого является cl, использует методы базового класса.

Результат программы COUNTEN

В функции main() происходят следующие действия: мы трижды увеличиваем cl, ныводим значение на экран, затем дважды уменьшаем и вновь выводим на экран.

cl = 0 - после инициализации

cl = 3 - после увеличения cl

Cl=I - после уменьшения Cl

Конструкторы, методы operator++() и get_count() класса Counter и метод operator~() класса CountDn работают с объектом класса CountDn

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

Мы научились расширять возможности класса почти без модификации его кода. Рассмотрим, что же мы все-таки изменили в классе Counter.

Данные классов, с которыми мы ранее познакомились, включая переменную counter класса Counter из примера C0UNTPP3, имели спецификатор доступа private. В программе COUNTEN переменная counter имеет другой спецификатор доступа: protected. Рассмотрим его предназначение.

Вспомним, что нам известно о спецификаторах доступа private и public. Из методов класса есть доступ к членам (полям и методам) класса, если они имеют любой из этих спецификаторов. Но при использовании объекта, объявленного в программе, можно получить доступ только к данным со спецификатором public (например, используя операцию точки). Предположим, что есть объект objA класса А. Метод funcA() является методом класса А. Оператор функции main() (или любой другой функции, не являющейся методом класса А)

objA.funcA ( );

будет ошибочным, пока мы не объявим funcA() как public. Для объекта objA мы не можем использовать члены класса А, объявленные как private. Их могут использовать только методы самого класса А. Это показано на рис. 9.3.

Одцако при использовании наследования у нас появляется еще ряд добавочных возможностей. Возникает вопрос, могут ли методы производного класса иметь доступ к членам базового класса? Другими словами, может ли operator~() класса CountDn иметь доступ к полю count класса Counter? Ответ будет таким: методы производного класса имеют доступ к членам базового класса, если они имеют спецификатор доступа public или protected. К членам, объявленным как private, доступа нет.

Мы не хотим объявлять поле count как public, так как это разрешит доступ к ней из любой функции программы, уничтожив возможность сокрытия данных. Член, объявленный как protected, доступен методам своего класса и методам любо- Базовый и производный классы 367

го производного класса. При этом он не будет доступным из функций, не принадлежащих к этим классам, например из функции main(). Это показано на рис. 9.4.

class А

Объект класса А имеет доступ только к общедоступным членам А

Рис. 9.3. Спецификаторы доступа в ситуации без наследования

class Base

Derv ObjD

Рис. 9.4. Спецификаторы доступа в ситуации с наследованием

Таблица 9.1 отражает возможности использования спецификаторов доступа в различных ситуациях.

Таблица 9.1. Наследование и доступ

Специфиикатор Доступ из самого Доступ из производных Доступ из внешних
доступа класса классов классов и функций
public Есть Есть Есть
protected Есть Есть Нет
private Есть Нет Нет 368 Глава 9. Наследование

Таким образом, если вы пишете класс, который впоследствии будет использоваться как базовый класс при наследовании, то данные, к которым нужно будет иметь доступ, следует объявлять как protected.

Недостатки использования спецификатора protected

Следует знать, что существуют и недостатки использования спецификатора доступа protected. Допустим, вы написали библиотеку классов и публично ее распространяете. Любой программист сможет получить доступ к членам классов, объявленным как protected, просто создавая производные классы. Это делает члены, объявленные как protected, значительно менее защищенными, чем объявленные как private. Чтобы избежать порчи данных, часто приходится разрешать доступ производным классам только к тем методам базового класса, которые объявлены как public. Однако использование спецификатора доступа protected упрощает программирование, и мы будем использовать эту возможность в дальнейших примерах. В будущем, при создании собственных программ, вам придется сделать выбор между преимуществами и недостатками спецификатора protected.
Предыдущая << 1 .. 132 133 134 135 136 137 < 138 > 139 140 141 142 143 144 .. 341 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100