21. Скомпилировать и запустить программу. Для проверки работы нужно последовательно нажать кнопки Create, Call и Destroy. После нажатия кнопки Call вы должны получить два сообщения с правильным ответом 200 и два сообщения с неправильным ответом 30.
В классах CleverDog и StupidDog есть методы с одинаковыми именами и сигнатурами. Правда, реализация этих методов отличается, так как объект StupidDog путает умножение и сложение.
Язык C++ позволяет производить «тихое» приведение типа объекта к типу базового класса. Именно это сделало возможным поместить все объекты CleverDog и StupidDog в один массив объектов типа Dog. Но изначально в классе Dog не было методов Add и Mult, и вызвать их инструкцией Dogs[i]->Mult() было невозможно. Чтобы исправить этот досадный недостаток, в классе Dog эти методы были объявлены. Но реализация этих методов отсутствует, так как она нужна только дочерним классам. Такие методы без реализации называются абстрактными методами, и класс, в котором есть хотя бы один абстрактный метод, тоже становится абстрактным. Абстрактный класс не может порождать объекты, зато он может гарантировать полиморфное поведение своих наследников. Чтобы при вызове в таком полиморфном стиле объект знал «свой» метод, метод должен быть объявлен как virtual (виртуальный), что и было сделано в рассматриваемом примере. Виртуальный метод сохраняет свою виртуальность далее по всей иерархии наследования.
Инкапсуляция
Поскольку принцип инкапсулирования говорит нам о сокрытии от внешнего мира деталей реализации класса (объекта) и о его независимом поведении, то в языке программирования для достижения этих целей должны существовать определенные технологии.
К подобным методикам можно отнести использование конструкторов и деструкторов. Эти методы позволяют подготовить объект к работе и осуществить «уборку рабочего места» к моменту, когда объект завершает свое существование.
Также инкапсуляция позволяет назначать методам и полям класса области видимости. Области видимости определяются директивами 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.11class Dog {
private:
int age;
public:
Dog();
…