Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2vcTnguyvU

.pdf
Скачиваний:
6
Добавлен:
15.04.2023
Размер:
955.27 Кб
Скачать

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ МУРМАНСКИЙ ГОСУДАРСТВЕННЫЙ ГУМАНИТАРНЫЙ УНИВЕРСИТЕТ

Л.В. Яковлева

Практикум по объектно-ориентированному

программированию в С++

Часть 2

МУРМАНСК

2011

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ МУРМАНСКИЙ ГОСУДАРСТВЕННЫЙ ГУМАНИТАРНЫЙ УНИВЕРСИТЕТ

Л.В. Яковлева

Практикум по объектно-ориентированному

программированию в С++

Учебно-методическое пособие

Часть 2

МУРМАНСК

2011

УДК 004.434(075.8) ББК 32.973.26-018.1я73

Я47

Печатается по решению Совета по научно-исследовательской работе и редакционно-издательской деятельности Мурманского государственного гуманитарного университета

Рекомендовано учебно-методическим советом МГГУ к использованию в учебном процессе (протокол № 3 от 23.12.2010 г.)

Научный редактор: Б.М. Верещагин, канд. физ-мат. наук, доцент МГГУ

Рецензенты: В.В. Качала, канд. тех. наук, доцент, профессор кафедры информационных систем и прикладной математики МГТУ; Ю.В. Матвеев, начальник АСУ ООО «СЗРК-Мурманск»

Яковлева Л.В.

Практикум по объектно-ориентированному программированию в С++:

учебно-методическое пособие: в 2 ч. / науч. ред. Б.М. Верещагин. – Мурманск: МГГУ, 2011. – Часть 2. – 134 с.

Во второй части данного учебно-методического пособия рассматриваются такие основные концепции объектно-ориентированного программирования, как наследование, шаблоны классов, обработка исключений, абстракция итераторов, использование стандартных потоков ввода-вывода, а также классы STL. Каждая глава представляет студентам специфические возможности языка С++. Вторая часть учебно-методического пособия включает семь глав, в которых постепенно раскрываются тонкости методологии объектно-ориентированного программирования. Многочисленные упражнения и примеры помогут студентам проверить свое понимание ключевых концепций ООП и применить их на практике.

Предназначено для аудиторной работы студентов по специальности 010501 «Прикладная математика и информатика».

Печатается в авторской редакции.

Яковлева Л.В., 2011

Оформление. ГОУВПО «Мурманский государственный гуманитарный университет», 2011

Введение

Учебно-методическое пособие “Практикум по объектноориентированному программированию в С++ “ разработано на основе ГОС ВПО 2-го поколения (дата утверждения 23.03.2000г) для студентов, обучающихся по специальности 010501 “Прикладная математика и информатика”. В первой части данного учебно-методического пособия представлены такие аспекты языка С++, как механизм конструирования классов, перегрузка функций и операций, использование шаблонных функций. Во второй части учебно-методического пособия рассматриваются такие важные темы объектно-ориентированного программирования, как наследование, идентификация типа во время выполнения, обработка исключений, подробно обсуждается использование библиотеки ввода-вывода iostream и основных составляющих компонентов стандартной библиотеки STL.

В пятой главе представлены шаблонные классы. Шаблон класса можно рассматривать как алгоритм создания экземпляра класса, в котором параметры шаблона подлежат замене на конкретные значения типов или констант.

В шестой и седьмой главах разбирается парадигма объектгоориентированного программирования - наследование. Рассматриваются сложные случаи наследования: множественное и виртуальное. В седьмой главе также приведено понятие идентификации типа во время выполнения (RTTI ). RTTI позволяет программе запросить у полиморфного объекта класса информацию о его типе во время выполнения.

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

Вдевятой главе представлена обработка исключений. Приведены примеры, иллюстрирующие возбуждение и обработку исключений типа класса.

Вдесятой главе подробно обсуждается использование библиотеки ввода/вывода iostream. На примерах показаны основные возможности потоковых операций ввода/вывода.

Одиннадцатая глава посвящена контейнерам и алгоритмам из стандартной библиотеки С++ (standard template library — STL). В ней продемонстрированы описание и использование контейнеров (таких как vector, list и map), итераторов и обобщенных алгоритмов.

Цель данного курса состоит в том, чтобы на основе пользовательских классов языка С++ изучить использование таких парадигм объектно-

3

ориентированного программирования, как наследование и полиморфизм. Эта цель конкретизируется в следующих задачах:

применение обобщенного программирования;

анализ технологий безопасности исключений;

разработка классов с учетом наследования и полиморфизма;

построение эффективных объектно-ориентированных проектов для прикладной математики на языке С++ с использованием библиотек STL.

Вторая часть учебно-методического пособия “Практикум по объектноориентированному программированию в С++” предназначена для обеспечения будущих выпускников по специальности 010501 ”Прикладная математика и информатика“ специальными компетентностями в области объектно-ориентированного программирования, в частности, такими знаниями и умениями, как:

проектировать шаблонные классы, в том числе и с учетом наследования;

использовать наследование классов и динамическое связывание типов, в том числе, множественное и виртуальное;

использовать библиотеку ввода/вывода iostream в создаваемых классах;

реализовывать абстрактные контейнеры и обобщенные алгоритмы . Содержание дисциплины “Практикум на ЭВМ” - третий семестр специальности 010501”Прикладная математика и информатика“ представлено в следующей таблице:

 

Количество часов

 

 

 

Наименование темы

Всего

Лекц.

Лаб.

Сам.

 

 

аудит.

 

работы

раб.

1

Классы и объекты

6

2

4

1

2

Перегруженные функции

4

2

2

 

3

Перегрузка операторов и

6

2

4

1

 

преобразования, определенные

 

 

 

 

 

пользователем

 

 

 

 

4

Шаблоны функций

4

1

3

1

5

Шаблоны классов

6

1

5

1

6

Наследование

6

2

4

1

7

Абстрактные классы,

6

1

5

1

 

динамическая информация о

 

 

 

 

 

типе

 

 

 

 

8

Классы и динамическая

6

1

5

1

 

память

 

 

 

 

9

Исключения

4

1

3

 

10

Потоковый ввод-вывод

4

1

3

 

11

Стандартная библиотека

8

2

6

1

 

шаблонов

 

 

 

 

 

Всего

60

16

44

8

Каждая тема представлена отдельной главой. Главы обычно имеют такую структуру: концепции ООП, работающий код, декомпозиция программ, упражнения. Каждая глава имеет несколько важных примеров программ. Задания в лабораторных работах расширяют понимание основных парадигм ООП. Все программы были протестированы на платформе операционной системы Windows , используя среду разработки Microsoft Visual Studio 2008 и Bloodshed Dev-C++.

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

Глава 5. Шаблоны классов

Классы также могут быть параметризованы одним или несколькими типами. Примером такой возможности могут служить классы контейнеров, которые применяются для работы с элементами определенного типа. В этой главе в качестве примера шаблона класса рассматривается стек.

Реализация шаблона класса Stack

Для реализации шаблона класса используется шаблон класса vector стандартной библиотеки C++. Таким образом, отпадает необходимость заниматься реализацией управления памятью, конструктора копирования и оператора присваивания и можно сосредоточиться только на интерфейсе шаблона класса.

#include <cstdlib> #include <iostream> #include <vector> #include <stdexcept> using namespace std; template < class T> class Stack { private:

std::vector<T> elems; // Элементы коллекции public:

void push(T const&); // Добавление элемента

void pop();

// Снятие элемента

T top() const;

// Возврат элемента с вершины стека

bool empty() const { // Возвращает true, если стек пуст return elems.empty(); }

};

template <class T>

void Stack<T>::push(T const& elem) { elems.push_back(elem) ;

// Добавление в стек копии передаваемого элемента

}

template <class T> void Stack<T>::pop() { if (elems.empty()) {

throw std:: out_of_range (" Stack< >: : pop () : empty stack"); } elems .pop_back() ; // Удаление последнего элемента } template <class T> T Stack<T>::top() const {

if (elems.empty())

{ throw std::out_of_range (" Stack< >: : top () : empty stack"); } 6

return elems.back(); }// Возврат копии последнего элемента Объявление шаблона класса выполняется аналогично объявлению

шаблона функции: ему должна предшествовать инструкция, которая объявляет некоторый идентификатор в качестве параметра типа.

template <typename T> class Stack { }; или

template <class T> class Stack { };

Как и для шаблонов функций, вместо ключевого слова typename можно применять ключевое слово class. Внутри шаблона класса идентификатор Т можно использовать в объявлениях членов и функций-членов так же, как и любой другой тип. В данном примере параметр Т используется для объявления типа элементов как вектора значений с типом Т, для объявления push () как функции-члена класса, которая получает в качестве аргумента константную ссылку на объект типа Т, и для объявления функции top (), которая возвращает элемент типа Т.

template <typename T> class Stack { private:

std::vector<T> elems; // Элементы public:

Stack(); // Конструктор

void push(T const&); // Добавление элемента void pop(); // Снятие элемента со стека

Т top() const; }; // Возврат элемента с вершины стека

Класс имеет тип Stack<T>, где Т является параметром шаблона. Таким образом, каждый раз, когда требуется использовать тип этого класса в объявлении, следует указывать Stack<T>. Если, например, необходимо объявить собственные конструктор копирования и оператор присвоения, это должно выглядеть так:

template <class T> class Stack {

Stack (Stack<T> const&); // Конструктор копирования

Stack<T>& operator = (Stack<T> const &c); }// Оператор присвоения Однако если требуется указать имя, а не тип класса, следует использовать только Stack. Это делается при указании имени класса, его конструктора и деструктора.

Реализация функций-членов

Для того чтобы определить функцию-член шаблона класса, нужно указать, что это шаблон функции. При этом необходимо использовать полное имя типа шаблона класса. Таким образом, реализация функции-члена push () типа Stack<T> имеет следующий вид:

7

template <class T> void Stack<T>::push(T const& elem) { elems.push_back(elem) ; } // Добавление копии элемента в стек

Здесь для элемента вектора вызывается функция push_back (), которая и добавляет передаваемый в качестве параметра элемент в конец вектора. Заметим, что функция pop_back () вектора удаляет последний элемент, но не возвращает его, что связано с вопросами безопасности исключений. Реализовать полностью безопасную в плане исключений функцию pop (), которая возвращает удаленный элемент, невозможно. Однако если игнорировать небезопасность данной функции в плане исключений, то можно написать функцию pop (), возвращающую только что удаленный элемент. Здесь Т используется просто для объявления локальной переменной соответствующего типа.

template <class T> void Stack<T>::pop() { if (elems.empty()) {

throw std: :out_of_range (" Stack:: pop () ; → empty stack"); }

T elem = elems.back(); // Сохранение копии последнего элемента elems.pop_back(); // Его удаление

return elem; } // Возврат сохраненной копии элемента

Поскольку поведение функции вектора back () (возвращающей последний элемент) и функции pop_back () (удаляющей последний элемент) не определено для случая, когда вектор не содержит ни одного элемента, требуется проверка, не является ли стек пустым. Если он пуст, генерируется исключение типа std: :out_of_range. Такое же исключение генерируется и в функции top (), которая возвращает (но не удаляет) элемент, находящийся на вершине стека.

template <class T> Т Stack<T>::top() const { if (elems.empty()) {

throw std::out_of_range("Stack ::top(): empty stack"); } return elems.back(); } // Возврат копии последнего элемента

Функции-члены шаблонов классов можно реализовать как встраиваемые функции, располагающиеся внутри объявления класса, например:

template <class T> class Stack{ void push (T const& elem) { elems.push_back(elem); }; // Добавление копии элемента в стек

Использование шаблона класса Stack

Для того чтобы использовать объект шаблона класса, необходимо явно указать аргументы шаблона. В приведенном ниже примере проиллюстрировано применение шаблона класса Stack

#include <iostream> #include <string>

8

#include <cstdlib> using namespace std;

int main(int argc, char *argv[]) { try {

Stack<int> intStack; // Стек элементов типа int Stack<string> stringStack; // Стек элементов типа string

//Работа со стеком целых чисел intStack.push(7); cout<<intStack.top() << endl;

//Работа со стеком строк stringStack.push("PMI"); cout<<stringStack.top( ) <<endl; stringStack.pop( ); stringStack.pop( ) ;

} catch (exception const& ex) {

cerr <<"Exception: " << ex.what()<< std::endl; } system("PAUSE");

return EXIT_SUCCESS; }

Объявление Stack<int> указывает, что внутри шаблона класса в

качестве типа Т будет использоваться int. Таким образом, intStack создается как объект на базе вектора с элементами типа int, и для всех вызываемых функций-членов инстанцируется код для этого типа. Точно так же, путем объявления и использования Stack<std::string>, создается объект на базе вектора, элементами которого являются строки, и для каждой из вызываемых функций-элементов инстанцируется код для этого типа. Заметим, что инстанцирование происходит только для вызываемых функций-членов. Для шаблонов классов экземпляры функций-членов инстанцируются только при их использовании. Аргументы шаблона могут быть любого типа, например указателями на float или даже стеками целых чисел.

Stack<float*> floatPtrStack;

//Стек указателей на значения float Stack<Stack<int> > intStackStack;

//Стек стеков значений int

Должно выполняться только одно требование: чтобы любая вызываемая операция для данного типа была допустима. Обратите внимание, что между двумя закрывающими угловыми скобками следует помещать пробел. Если этого не делать, то две угловые скобки будут интерпретироваться как оператор >>, что приведет к синтаксической ошибке.

Stack<Stack<int> > intStackStack; //ошибка : >> не допускается

9

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]