Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Книга C++.doc
Скачиваний:
24
Добавлен:
10.11.2019
Размер:
2.48 Mб
Скачать

Класс вектор. Часть 3.

Итак, финальная часть. Использование класса ВЕКТОР.

#include <iostream.h>

#include "Vector.h"

void main()

{

Vector v(4); // Создание вектора

cin >> v; // Ввод компонент ветрора

cout << !--(v*5) << endl; // Вывод длины заданного вектора

}

Домашнее задание

  1. Создайте класс защищенного массива, в котором реализована проверка выхода за границы массива. Перегрузите операторы: [ ], =, +, -, <<, >>

  2. Создайте класс Время, в котором реализованы операции сложения, вычитания, сравнения, ввода и вывод на экран. Возможность конвертации времени из американского формата am (pm): 10:00 pm = 22:00, 12:00 pm =00:00

  3. Используя принципы ООП опишите класс стек. Используйте этот класс в программе, которая "переворачивает" строку.

Стек — одна из наиболее полезных стандартных структур данных. Он позволяет производить вставку и удаление данных только в одном месте — верхушке стека.

Представьте себе стопку тарелок. Добавлять/ удалять тарелки из стопки можно разными способами, например:

  • ставить тарелку в верх стопки, и убирать с верха;

  • ставить тарелку в верх стопки, убирать снизу стопки

  • ставить тарелку в середину стопки, убирать снизу стопки и т.д.

Так вот, если мы представим себе организацию работы по принципу стека, то когда тарелка ставится на стопку, она всегда помещается на ее вершину (это называется поместить в стек - pushing onto the stack), а когда тарелка убирается из стопки, то всегда убирается тарелка с ее вершины (это называется вытолкнуть из стека - popping off the stack).

Стеки известы как структуры данных типа последним пришел — первым вышел (last-in, first-out — LIFO) - последний элемент, помещенный в стек, является первым элементом, выталкиваемым (удаляемым) из стека. Обычно стек позволяет операции push, pop, top, empty и full. Операция push помещает значение в стек. Операция pop восстанавливает значение и удаляет его стека. Операция top возвращает верхнее значение стека. Операция empty проверяет, пуст ли стек, и операция full, проверяет полон ли стек.

Наследование (Inheritance). Часть 1.

С понятием ''наследование'' Вы уже познакомились на первом занятии посвященному объектно-ориентированому программированию. Тем не менее, если при чтении оглавления у Вас возник вопрос: ''Что такое ''наследование'' ?'', не расстраивайтесь, у Вас есть возможность повторить этот материал.

Итак, Вы уже слышали, что наследование является одним из фундаментальных понятий ООП. Но в чем же состоит его фундаментальность? Почему это понятие является базовым для ООП? И, в конечном итоге, что это дает нам, программистам, в плане облегчения задачи написания программ? Особенностью ООП является поощрение повторного использования кода при помощи механизма наследовния. Многие типы представляют собой вариации на темы существующих. Согласитесь, утомительно разрабатывать новый код для каждого из них и, кроме того, новый код - новые ошибки. Смысл и универсальность наследования заключается в том, что не надо каждый раз заново описывать новый объект, а можно указать родителя (базовый класс) и описать отличительные особенности нового класса. В результате, новый объект будет обладать всеми свойствами родительского класса плюс своими собственными отличительными особенностями. Итак, новый класс производится от существующего, называемого базовым классом. Производный касс использует члены базового класса, но может также изменять и дополнять их. Таким образом, мы выигруем во времени, и ненужно лишний раз нажимать клавиши. Рассмотрим пример:

Можно создать какой-то базовый класс "транспортное средство", который универсален для всех средств передвижения, к примеру, на 4-х колесах. Этот класс "знает" как двигаются колеса, как они поворачивают, тормозят и т.д. А затем на основе этого класса создадим класс "легковой автомобиль", который унаследуем из класса "транспортное средство". Поскольку, мы новый класс унаследовали из класса "транспортное средство", то мы унаследовали и все особенности этого класса и нам не надо в очередной раз описывать как двигаются колеса и т.д. Мы просто добавим те черты, особенности поведения, которые характерны для легковых автомобилей. В то же время мы можем взять за основу этот же класс "транспортное средство" и построить класс "грузовые автомобили". Описав отличительные особенности грузовых автомобилей, мы получим уже новый класс "грузовые автомобили". А, к примеру, на основании класса "грузовой автомобиль" уже можно описать определенный подкласс грузовиков и т.д. Таким образом, нам не надо каждый раз описывать все "с нуля". В этом и заключается главное преимущество использования механизма наследования. Мы как бы сначала формируем простой шаблон, а затем все усложняя и конкретизируя, поэтапно создаем все более сложный шаблон.

Надеемся, что суть наследования Вам уже понятна и, согласитесь, этот механизм очень может помочь при разработке программ. Формальное определение наследования следующее:

Наследование - это процесс, посредством которого, один объект может наследовать свойства другого объекта и добавлять к ним черты, характерные только для него.

Обратите внимание, что само понятие наследование показывает отношение между классами. Так вот, отношения наследования иерархичны. Не пугайтесь этого слова, а вспомните следующий пример из жизни: рядовой не может отдавать приказания генералу. Почему?.. Согласно иерархии чинов. Классики объектно-ориентированого программирования счетают, что иерархия - это метод, позволяющий копировать элементы во всем их многообразии и сложности. Для нас важен лишь тот факт, что с помощью иерархии, мы можем произвести классификацию объектов. Например, КАМАЗ с номерным знаком 157OEA- прежде всего является КАМАЗом, КАМАЗ - это грузовой автомобиль, в свою очередь, грузовой автомобиль это автомобиль, а автомобиль - это транспортное средство. Такая иерархия позволяет легко толковать поведение объекта (в нашем случае, это КАМАЗ с номерным знаком 157OEA)

Итак, рассмотрев теоретические вопросы, переходим к практике. Класс можно сделать производным от существующего с использованием следующей формы:

class имя_класса:

(public| protected| private) имя_базового_класса

{

объяления членов

};

Синтаксис описания класса Вам уже знаком. А для создания наследника от базового класса необходимо после имени класса поставить двоеточие, записать спецификатор доступа и указать родителя (т.е. базовый класс). Следующий пример познакомит нас с синтаксисом наследования в С++. В примере приведено описание базового класса (Base1), public-производного класса (PublicDerived1) и private-производного класса (PrivateDerived1). Для иллюстрации всех изменений в разграничении доступа эти классы имеют поля данных и функции-члены в каждой из закрытой, защищенной и открытой частях. Объекты (они же экземпляры класса) всех классов объявлены в функции main:

class Base1 //создание базового класса

{

private: //закрытые данные

int data1;

int function1();

protected: //защищенные данные

int data2;

int function2();

public: //открытые данные

int data3;

int function3();

};

class PublicDerived1:public Base1 //создание public-производного класса

{

private: //закрытые данные

int data4;

int function4();

protected: //защищенные данные

int data5;

int function5();

public: //открытые данные

int data6;

int function6();

};

class PrivateDerived1:private Base1 //создание private-производного класса

{

private: //закрытые данные

int data7;

int function7();

protected: //защищенные данные

int data8;

int function8();

public: //открытые данные

int data9;

int function9();

};

void main()

{

Base1 aBase1; //экземпляр базового класса

PublicDerived1 aPublicDerived1; //экземпляр public-производного класса

PrivateDerived1 aPrivateDerived1; //экземпляр private-производного класса

}

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

Возвратимся к нашему примеру и разберем правила доступа к закрытым, защищенным и открытым частям классов Base1, PublicDerived1 и PrivateDerived1. Т.е. выясним что к чему имеет доступ...

Доступ к протоколу класса. Обращаем Ваше внимание на то, что описание класса имеет доступ ко всем своим собственным частям. Вполне естественно, что любая функция-член в закрытой, защищенной или открытой частях описания класса имеет прямой доступ ко всем полям данных и всем функциям-членам описания своего класса. Таким образом, любая функция-член в классе Base1 имеет прямой доступ к data1, data2, data3, function1, function2 и function3. Аналогично, любая функция-член класса PublicDerived1 имеет прямой доступ к data4, data5, data6, function4, function5 и function6. Любая функция-член в классе Private-Derived имеет прямой доступ к data7, data8, data9, function7, function8, function9.

Доступ через протокол производного класса. Производные классы наследуют все протоколы (включая все поля данных и функции-члены) от своего базового класса. Однако, производный класс не имеет прямого доступа к полям данных или функциям-членам, определенным в закрытой части его базового класса. Классы PublicDerived1 и PrivateDerived1 наследуют data1 и function1 от своего базового класса (Base1), но не имеют прямого доступа к ним. Доступ можно обеспечить через функцию, определенную в защищенной или открытой частях класса Base1. Эта функция будет наследоваться открытыми и защищенными производными классами и будет доступна им.

Доступ через объекты класса. Объекты класса не имеют доступа к закрытой и защищенной частям описания класса. Они не могут получить прямой доступ к полям данных в закрытой и защищенной частях. Таким образом, объект aBase1 не имеет доступ к своим собственным закрытым элементам data1 и function1. Аналогично, объект aBase1 не имеет доступа к своим собственным защищенным элементам data2 и function2.

Доступ через объекты public-производного класса. Объекты public-производного класса не имеют доступа к закрытой и защищенной части базового класса. Если в классе Base1 определены открытые функции для доступа к закрытым или защищенным полям через объекты классов, то эти функции наследуются public-производными классами и могут использоваться объектами этих классов. Объекту aPublicDerived1 недоступны его собственные закрытые элементы data4 и function4.

Доступ через объекты private-производного класса. Объекты private-производного класса не имеют доступа к закрытой части их базового класса. Элементы data1 и function1 недоступны объекту aPrivateDerived1. Если в классе Base1 определены открытые функции для доступа к закрытым полям через объекты классов, то эти функции наследуются public-производными классами и могут использоваться объектами этих классов.

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

  1. Элементы, объявленные как закрытые (private), могут использоваться любыми функциями-членами своего класса.

  2. Элементы, объявленные как защищенные (protected), могут использоваться любыми функциями-членами своего класса, а также функциями-членами производных классов.

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

  4. Когда класс используется как открытый базовый класс, его открытые элементы становятся открытыми элементами производного класса, а защищенные элементы становятся защищенными элементами производного класса.

  5. Когда класс используется как закрытый базовый класс, его открытые и защищенные элементы становятся закрытыми элементами производного класса.

  6. Когда класс используется как защищенный базовый класс, его открытые и защищенные элементы становятся защищенными элементами производного класса.