- •Экзамен 374 Предварительные рассуждения Вступительное слово
- •Исторические факты
- •Начнем!
- •Проба пера
- •Открытие сохраненного проекта
- •Вывод данных
- •Типы данных
- •Хороший стиль программирования
- •Переменные и константы
- •Практический пример
- •Ввод данных
- •Например:
- •Пример:
- •Арифметические операции с числами
- •Литералы
- •Некоторые примеры
- •Домашнее задание
- •Напишите программу, которая вводит число из трех цифр, разделяет число на отдельные цифры и печатает их отдельно друг от друга с тремя пробелами между ними. Преобразование типов
- •Перечисляемые типы
- •Типичная ошибка
- •Хороший стиль программирования
- •Типичная ошибка
- •Выражения
- •Оператор if
- •Структура программы
- •Логические операции
- •Структура множественного выбора switch
- •Практический пример
- •Цикл for
- •Практический пример
- •Цикл do-while
- •Домашнее задание
- •Вызов функции
- •Прототипы функций
- •Разбор программы
- •Область видимости
- •Аргументы по умолчанию
- •Встраивание
- •Перегрузка функций
- •Учебный пример перегруженных функций. Иллюстрация перегрузки
- •Результат работы программы
- •Практические примеры
- •Домашнее задание
- •Примеры домашней работы урока 1 Пример №1
- •Как работает программа
- •Пример №2
- •Как работает программа
- •Примеры домашних работ на создание функций Пример №1
- •Как работает программа
- •Пример №2
- •Как работает программа
- •Массивы
- •Объявление массивов
- •Примеры использования массивов
- •Программа 1
- •Программа 2
- •Обратите внимание!
- •Типичная ошибка программирования
- •Типичная ошибка программирования
- •Программа 3
- •Типичная ошибка программирования
- •Замечание по технике программирования
- •Программа 4
- •Программа 5
- •Программа нахождения минимального и максимального элементов массива
- •Сортировка массивов
- •Домашнее задание
- •Что такое указатели?
- •За кулисами...
- •Как работать с указателями?..
- •Зачем нужны указатели?
- •Указатели и Массивы.
- •Примеры задач
- •Пример 1
- •Пример 2
- •Пример 3
- •Указатели - аргументы функций.
- •Ссылочные параметры
- •Примеры решения задач
- •Домашнее задание
- •Операторы свободной памяти new и delete
- •Функции работы со строками из библиотеки обработки строк
- •Пример 1.
- •Пример2
- •Пример 3
- •Пример задачи на новый материал
- •Домашнее задание
- •Двухмерные массивы, как частный случай многомерных массивов
- •Программа.
- •Результаты работы программы.
- •Многомерные динамические массивы
- •Пример на многомерные динамические массивы
- •Домашнее задание
- •Рекурсия
- •Рекурсии или итерации
- •Указатели на функции
- •Пример №1
- •Результат выполнения программы:
- •Пример №2
- •Результат выполнения программы
- •Пример №3
- •Результаты выполнения программы
- •Определения структур
- •Пример #1 на использование структур
- •Пример #2 на использование структур
- •Оператор указателя на структуру
- •Домашнее задание
- •Тест по c Группа ___________________ф. И. О. ______________________
- •Объектно-ориентированное программирование.
- •Наследование (Inheritance).
- •Инкапсуляция (Encapsulation).
- •Определение класса
- •Конструкторы и деструкторы Инициализация объектов класса: конструкторы
- •Основное назначение конструкторов - инициализация объектов.
- •Использование конструкторов с аргументами по умолчанию
- •Если параметры не передаются конструктору, в определении объекта не нужно включать пустые круглые скобки.
- •Использование деструкторов
- •Когда вызываются конструкторы и деструкторы.
- •Домашнее задание
- •Конструктор копирования
- •Синтаксис конструктора копирования
- •Памятка
- •Пример использования конструктора копирования.
- •Перегруженные конструкторы
- •Экскурс в историю
- •Послесловие к примеру
- •Маленькое замечание
- •Домашнее задание
- •Создание класса ''строка''
- •Перегрузка операций.
- •Общие принципы перегрузки операторов.
- •Преобразования, определяемые классом
- •Пример строкового класса с перегруженными операторами
- •Домашнее задание
- •Дружественные функции (Friend Functions)
- •Пример строкового класса с перегруженными операторами и дружественными функциями
- •Перегрузка операторов new и delete
- •Перегрузка оператора индексирования
- •Класс вектор. Часть1.
- •Класс вектор. Часть 2.
- •Класс вектор. Часть 3.
- •Домашнее задание
- •Наследование (Inheritance). Часть 1.
- •Наследование (Inheritance). Часть 2.
- •Множественное наследование (multiple inheritance)
- •Пример множественного наследования
- •Домашнее задание
- •Статические члены данных
- •Раннее и позднее связывание
- •Виртуальные функции
- •Пример.
- •Абстрактные классы
- •Виртуальный базовый класс
- •Практический пример
- •Домашнее задание
- •Потоки ввода-вывода.
- •Iostream.H: stream - поток, "I" - сокр. Input - ввод, "o" - сокр. Output - вывод.
- •Предопределенные потоки.
- •Операции помещения в поток и извлечения из потока.
- •Файловый ввод-вывод с применением потоков.
- •Конструкторы файловых потоков.
- •Функции для открытия и закрытия файлов.
- •Функции для обмена с потоками.
- •Часто применяемые функции потока.
- •Ввод/вывод массива в/из файл(-а).
- •Практический пример: перекодировка файла.
- •Домашнее задание
- •Немного о файлах...
- •И снова файлы...
- •Пример "Телефонная книга"
- •Файл abonent.H
- •Форматирование данных при обменах с потоками.
- •Состояние потока.
- •Использование аргументов командной строки.
- •Ввод/вывод в с.
- •Домашнее задание
- •Определение шаблонов функций
- •Переопределение шаблонов функций
- •Шаблоны классов
- •Шаблонный класс вектор
- •Шаблонный класс вектор
- •Шаблонный класс вектор
- •Введение
- •Обработка исключительных ситуаций
- •Практический пример
- •Программа
- •Домашнее задание
- •Экзамен
Переопределение шаблонов функций
Каждая версия функции, генерируемая с помощью шаблона, содержит одинаковый базовый код. Единственным изменяемым свойством функции будут значение параметра (или параметров) типа. Однако для отдельного параметра (или параметров) типа можно обеспечить специальную обработку. Для этого определяется обычная функция языка С++ с тем же именем, что и шаблон функции, но использующая уже имеющиеся типы данных, а не параметры типов. Обычная функция переопределяет шаблон. Т.е., если компилятор обнаруживает, что типы переданных параметров соответствуют спецификации обычной функции, то он вызовет ее, а не создаст функцию по шаблону.
Шаблоны классов
Вы уже знаете о создателе С++ Бьярне Страуструпе (Bjarne Stroustrup) и его фундаментальном труде "The C++ Programming Language". Примичателен следующий факт: все главы этой книги начинаются с цитаты. Что касется шаблонов, то Страуструп использовал следующую: "На этом месте Ваша цитата". Таким образом, после ознакомления с этим материалом, Вы сможете сами подобрать цитату к этому разделу.
В этом разделе мы познакомимся с обобщенными (иногда, Вы можете втсретить определение параметризованными) классами. И начнем, пожалуй, с обозрения недалекого прошлого.
Работу над определением шаблонов в языке С++ Страуструп ведет с 1986 года. В своей книге "The Design and Evolution of C++" Страуструп пишет: "В исходном проекте языка С++ параметризованные типы учитывались, однако, их реализация была отложена из-за нехватки времени на тщательное исследование и полноценную реализацию" (как видите, великим мира сего тоже не хватает времени... но они всегда выполняли домашнее задание). В результате нескольких лет работы, к 1990 году он представил эксперементальную разработку, реализующую эту возможность, в своей книге "Annotated C++ Reference Manual". Именно эта версия определения шаблона в 1990 году была добавлена к развивающемуся стандарту ANSI C++. Теперь эта возможность поддерживается всеми основными компиляторами С++. Так что, используя Microsoft Visual C++, Вы получаете полный доступ к миру шаблонов.
Одними из главных целей, которые преследовались при разработке шаблонов, являются эффективность и простота в использовании. Неэффективные средства параметризации уже существовали к тому времени и требовалось только реализовать новый эфективный подход. Также, Страуструп считал, что использование шаблонов должно быть простым с точки зрения программиста. Вполне логично, что если языковая возможность сложна в использовании, то пользоваться ею будут немногие. Однако, благодаря мастерству Страуструпа, сегодня стало возможным осуществить все эти цели. Реализация шаблонов представляет собой огромное достижение, представляющее собой существенное дополнение к языку, как в смысле функциональности, так и в эстетическом совершенстве.
Итак, мы с Вами выяснили, что в С++ существует возможность определить обобщенный класс. Это значит, что Вы можете создать класс, который определяет все используемые в нем алгоритмы, но реальный тип обрабатываемых данных будет задан как параметр при создании объектов этого класса. Другими словами, когда Вам необходимо разработать класс, который имеет одинаковую логику работы с разными типами данных (например, класс ВЕКТОР, котрый одинаково работал бы как c данными типа int так и с double, Вашими собстенными типами данных), то лучше всего воспользоваться механизмом шаблонов.
Вот как выглядит общая форма объявления параметризованного (обобщенного) класса.
template <class Tтип_данных> class имя_класса {
//....описание класса.......
};
Рассомотрим это объявление. Здесь Tтип_данных представляет собой имя типа шаблона, которое в каждом случае конкретезации будет замещаться фактическим типом данных. При необходимости, можно определить более одного параметризовнного типа данных, используя список с разделителем-запятой, т.е. параметризованные классы могут иметь несколько аргументов шаблона. Заметим, что в пределах определения класса имя Tтип_данных можно использовать в любом месте. Когда создан параметризованный класс, Вы можете создать конкретную реализацию этого класса, используя следующий синтаксис:
имя_класса <тип_данных> объект;
В приведенном синтаксисе тип_данных представляет собою имя типа данных, над которыми фактически оперирует класс, и заменяет собой переменную Tтип_данных
Обращаем Ваше внимание также на тот факт, что функции-члены обобщенного класса автоматически являются обобщенными. Таким образом, их необязательно декларировать как параметризованные с помощью ключевого слова template, если Вы пишите реализацию этих функций внутри класса.
Рассмотрим небольшой пример, посвященный шаблонам. В примере рассматривается новый для Вас синтаксис, и, поэтому, этот пример можно отнести к разряду учебных. Практический пример, как всегда, Вас ожидает в конце этого занятия.
#include <iostream.h>
//Небольшой пример на использование параметризованных классов
//собственно сам параметризованный класс
template <class T> class TestClass {
private:
T tempo;//объявим поле tempo
//какого она будет типа?
//это можно бужет выяснить ТОЛЬКО во
//время создания конкретного экземпляра класса
public:
TestClass(){tempo=0;}
T testFunc();//тестируемая функция
};
//функция-член класса TestClass
//Так как метод реализован вне класса,
//используем явное упоминание template
template <class T>
T TestClass<T>::testFunc() {
//программа выводит на экран количество байт
//занимаемое переменной tempo, типа T
cout<<"Type's size is: "<<sizeof(tempo)<<endl;
return tempo;
}
void main()
{
//создадим конкретные экземпляры класса TestClass
//char
TestClass<char> ClassChar;
ClassChar.testFunc();
//int
TestClass<int> ClassInt;
ClassInt.testFunc();
//double
TestClass<double> ClassDouble;
ClassDouble.testFunc();
}
Отметим, также, следующее особенности работы с парметризованными классами. Обобщенные классы могут содержать "друзей". Причем, если дружественная функция не использует спецификацию шаблона, то она универсальна - имеется единственный ее экземпляр для всех случаев параметризованного класса. Дружественная функция, которая использует аргументы шаблона, специфична для каждого варианта класса, то есть для разных вариантов класса, создаются разные варианты дружественной функции.
В заключении, еще раз напомним, что обобщенные классы полезно использовать в тех случаях, когда класс содержит обобщенную логику. Проще говоря, используя обобщенный класс, можно создать класс, который будет управлять стеком и т.д. для любого типа данных. Компилятор автоматически сгенерирует корректный код объекта на основе типа, задаваемого при создании этого объекта.