Также инкапсуляция позволяет назначать методам и полям класса области видимости. Области видимости определяются директивами private, protected, public и friend. Эти модификаторы будут рассматриваться ниже.
Модификатор private
Все члены класса, объявленные после этой директивы, видимы только для членов этого класса. Это значит, что любые методы класса могут вызывать private-методы и изменять или читать private-поля данного класса, но ни один класс (или объект) извне не может получить доступ к данным полям и методам. Таким образом, члены класса, помещенные в раздел private, предназначаются исключительно для использования внутри класса. Для внешних структур они невидимы. По умолчанию, все члены класса являются private, если явно не указано, к какой области видимости они принадлежат.
Модификатор protected
Члены класса, объявленные как protected, сохраняют все ограничения членов класса, объявленных как private, но дочерние классы могут к ним обращаться.
Таким образом, раздел protected предназначен для создания расширенной зоны видимости для наследников данного класса и одновременно реализует защиту от внешнего доступа со стороны объектов, не являющихся наследниками данного класса.
Модификатор public
Эти члены класса видимы всем и отовсюду, и являются интерфейсом класса, то есть набором полей и методов, специально определенных для взаимодействия с внешним миром.
Модификатор friend
От обсуждения предыдущих трех директив возникает устойчивое впечатление, что классы в своем поведении очень похожи на людей. У них есть приватная зона, куда не допускается никто, зона ограниченного доступа, куда допускаются только «члены семьи», и публичная зона, которую показывают всем. Еще большее сходство с людьми классы обретают тогда, когда мы узнаем, что они могут дружить. То есть реализация языка C++ позволяет совершенно посторонним классам по-дружески (friend) получать доступ к подробностям реализации класса. Можно объявить с этим модификатором как отдельные члены класса, так и весь класс целиком. Директива friend предназначена для обеспечения доступа к отдельным классам, к private и protected областям текущего класса, к отдельным членам из этих областей, или ко всем членам класса сразу.
Упражнение 5.1 (продолжение)
22. В ранее созданном классе Dog нужно перенести поле age из области public в область private, как показано в листинге 5.11.
Листинг 5.11
class Dog {
private:
int age;
public:
Dog();
…
23. Теперь нужно попробовать откомпилировать проект. Но будет выведено сообщение об ошибке \'age\': cannot access private member declared in class \'Dog\'. Член класса с модификатором private не виден извне, и попытка получить к нему доступ в коде обработчика кнопки Assign обречена на неудачу.
24. Переместить поле age в область protected, как показано в листинге 5.12.
Листинг 5.12
class Dog {
protected:
int age;
public:
Dog();
…
25. Попытка откомпилировать проект закончится так же, как и предыдущая, поскольку снова происходит обращение к полю protected извне класса. Когда поле находилось в зоне public, такой ошибки не было.
26. Изменить метод Add класса CleverDog, как показано в листинге 5.13.
Листинг 5.13
class CleverDog: public Dog {
void Add(int x, int y){
age= 200;
};
27. Изменить обработчик щелчка на кнопке Assign, как показано в листинге 5.14. Листинг 5.14
case IDC_BUTTON3:
Dogs[0]->Add(0,0);
break;
28. После внесения этих изменений проект нормально компилируется, и нажатие кнопки Assign не приводит к возникновению ошибки. Поскольку класс Dog является базовым классом для CleverDog, то метод Add дочернего класса получает доступ к полю age, объявленному в секции protected базового класса.
Перегрузка методов
Гибкость использования классов расширяется за счет использования перегрузки методов. Перегрузка методов позволяет объявлять в одном классе несколько методов с одним и тем же именем, но разным составом параметров. Этот принцип иллюстрируется в упражнении.
Упражнение 5.1 (продолжение)
29. Добавить в класс Dog еще один метод Speak(), объявление которого приведено в листинге 5.15. Этот метод почти ничем не отличается от уже существовавшего метода Speak(), кроме того, что он принимает в качестве параметра целое число и отображает его значение.
Листинг 5.15
void Speak(int x){
char mm[32];
wchar_t *szStr = L"";
wchar_t mstr[32];
sprintf(mm,"Перегрузка, значение параметра: %d", x);
mbstowcs(mstr, mm, 32);
szStr = mstr;
MessageBox(NULL, szStr, TEXT(«TUT»), 0);
};
30. Теперь нужно переписать обработчик щелчка на кнопке Assign, как показано в листинге 5.16. Листинг 5.16
case IDC_BUTTON3:
Dogs[0]->Speak();
Dogs[0]->Speak(350);
break;
Компиляция и выполнение программы пройдут без ошибок. В C++ для обозначения перегруженных функций не нужны никакие особенные директивы. Компилятор, встретив функции с одинаковыми именами, но разным составом параметров, сам понимает, что они перегружены, и во время вызова функции именно по параметрам определяет, какую именно из перегруженных функций надо вызывать.
Читать дальше
Конец ознакомительного отрывка
Купить книгу