- •Курс лекций по дисциплине “Основы программирования и алгоритмические языки” Бондарев в.М., Марченко ю.С. Введение
- •Основы алгоритмизации
- •1 Основные этапы решения задачи на эвм
- •1.1 Постановка задачи
- •1.2 Проектирование программы
- •1.3 Разработка алгоритма
- •1.4 Кодирование
- •1.5 Отладка и тестирование программы
- •2 Элементарные алгоритмические структуры
- •2.1 Последовательная алгоритмическая структура
- •2.2 Алгоритмическая структура выбора
- •2.3 Алгоритмическая структура повторения
- •2.4 Комбинация структур
- •2.5 Пошаговая детализация алгоритма
- •2.6 Разработка алгоритма вычисления Sin X
- •2.7 Разработка алгоритма подсчета простых чисел
- •3 Алгоритмы поиска
- •3.1 Поиск наибольшего среди вводимых чисел
- •3.2 Поиск наибольшего числа в массиве
- •3.3 Поиск заданного числа в массиве
- •3.4 Поиск с порогом
- •3.5 Двоичный поиск
- •4 Алгоритмы сортировки
- •4.1 Обменная сортировка
- •4.2 Сортировка слиянием
- •4.3 Сравнение двух алгоритмов сортировки
- •5 Рекурсивные алгоритмы
- •5.1 Простая рекурсия
- •5.2 Ханойские башни
- •5.3 Быстрая обменная сортировка
- •6.2 Простейшая программа
- •6.3 Составление простой программы
- •6.4 Программа сложение двух чисел
- •6.5 Организация повторений
- •6.6 Условный оператор
- •If (выражение) оператор [else оператор].
- •6.7 Оператор цикла for
- •7 Указатели и массивы
- •7.1 Указатели
- •7.2 Разыменование и разадресация
- •7.3 Операции new и delete
- •7.4 Массивы
- •7.5 Многомерные массивы
- •7.6 Связь между массивами и указателями
- •7.7 Массивы в динамической памяти
- •8 Строки и структуры
- •8.1 Встроенный тип char
- •8.2 Строки символов как массивы
- •8.3 Строковые библиотечные функции
- •8.4 Структуры
- •8.5 Объявление структур
- •8.6 Битовые поля
- •8.7 Объединения
- •9 Функции
- •9.1 Функция для сложения чисел
- •9.2 Ссылки
- •9.3 Выходные параметры функции
- •9.4 Ссылка — возвращаемое значение
- •9.5 Одномерные массивы как параметры
- •9.6 Двумерные массивы как параметры
- •10 Еще о функциях
- •10.1 Параметры по умолчанию
- •10.2 Произвольное число параметров
- •10.3 Неиспользуемые параметры
- •10.4 Перегруженные функции
- •10.5 Указатель на функцию
- •Void error(char* p) { /*тело ф-ции*/} ,
- •10.6 Спецификатор inline
- •Inline void error(char* p) { /*тело ф-ции*/}
- •10.7 Макросы
- •11 Ввод и вывод
- •11.1 Разновидности ввода и вывода
- •11.2 Открытие и закрытие потока
- •11.3 Ввод и вывод символов
- •11.4 Ввод и вывод строк
- •11.5 Ввод и вывод записей
- •11.6 Управление указателем файла
- •11.7 Состояние потока
- •11.8 Форматированный вывод
- •11.9 Форматированный ввод
- •11.10 Другие функции форматного ввода и вывода
- •12 Уточнение понятий языка
- •12.1 Объявление, определение, инициализация
- •12.2 Область видимости и время жизни
- •12.3 Типы
- •12.4 Производные типы
- •12.5 Числовые константы
- •12.6 Именные константы
- •12.7 Перечисление
- •12.8 Порядок вычисления выражений
- •13 Операции и операторы
- •13.1 Сводка операций
- •13.2 Сводка операторов
- •13.3 Оператор выражения
- •13.4 Оператор switch
- •13.5 Операторы break и continue
- •13.6 Оператор goto и метки
- •14 Классы
- •14.1 Определение класса
- •14.2 Инкапсуляция
- •14.3 Конструктор
- •14.4 Деструктор
- •14.5 Пример класса — список в динамической памяти
- •14.6 Указатель на себя
- •15 Производные классы
- •15.1 Простое наследование
- •15.2 Списки инициализации
- •15.3 Ключи доступа
- •15.4 Виртуальные функции
- •15.5 Реализация виртуальных функций
- •15.6 Полиморфизм
- •16 Еще о класcах
- •16.1 Статические элементы
- •16.2 Друзья класса
- •16.3 Перегрузка операций
- •16.4 Множественное наследование
- •17.1 Библиотека потоков
- •17.2 Предопределенные потоки
- •17.3 Операции помещения в поток и извлечения из потока
- •17.4 Форматирующие функции-элементы
- •17.5 Флаги форматирования
- •17.6 Манипуляторы
- •18 Еще о потоках
- •18.1 Ошибки потока
- •18.2 Опрос состояния потока
- •18.3 Файловый ввод-вывод с применением потоков
- •18.4 Конструкторы файловых потоков
- •18.5 Функции для открытия и закрытия файлов
- •18.6 Замена буфера потока
- •18.7 Текстовый и бинарный ввод-вывод
- •18.8 Бесформатный ввод и вывод
- •18.9. Часто применяемые функции потока
- •18.10 Форматирование в памяти
- •18.11 Дополнительные возможности ostrstream
- •19 Шаблоны
- •19.1 Шаблоны функций
- •19.2 Перегрузка и специализация шаблонов
- •19.3 Шаблоны классов
- •20 Директивы препроцесора
- •20.1 Директива #define
- •20.2 Директива #include
- •20.3 Условная компиляция
- •20.4 Директива #error
- •20.5 Директива #line
- •20.6 Директива #pragma
- •21.1 Адресация памяти
- •21.2 Модели памяти
- •21.3 Спецификация указателей
- •Int near* var_name;
- •Int* near var_name;
- •21.4 Макросы для указателей
- •21.5 Модификаторы переменных
- •21.6 Модификаторы функций
- •21.7 Соглашения о вызове
- •21.8 Встроенный код ассемблера
- •21.9 Псевдорегистры
- •Литература
- •Содержание
- •21.8 Встроенный код ассемблера ........................................................
- •21.9 Псевдорегистры ............................................................................
15.4 Виртуальные функции
Виртуальные функции позволяют уже в базовом классе обращаться к функциям, которые будут определены позже в производных классах.
Например, функция go( ), перемещающая рыбку (объект класса fish), рисует ее, вызывая метод draw( ). Этот метод перекрывается в каждом производном от fish классе, т.к. щуки выглядят иначе, чем караси или карпы. Если бы не было виртуальных функций, каждый производный класс перекрывал бы и метод go( ) тоже, т.к. go( ) для щук вызывает один метод draw( ), а go( ) для карпов — совсем другой. Возникло бы дублирование кода, поскольку этот метод общий для всех производных классов. Если же сделать функцию draw( ) виртуальной, один и тот же метод go( ), описанный в базовом классе, будет вызывать различные методы draw ( ) в зависимости от того, какому потомку он принадлежит
Чтобы сделать метод виртуальным, достаточно объявить его с описателем virtual, например
virtual void draw ();
Для виртуальных функций действуют следующие правила:
1) виртуальную функцию нельзя объявлять как static;
2) спецификатор virtual необязателен при переопределении функции в производном классе;
3) виртуальная функция должна быть определена в классе, где она впервые объявлена или должна быть чисто виртуальной, т.е. не иметь кода
virtual void draw()=0 .
Класс, содержащий чисто виртуальные функции, является абстрактным, объекты такого класса не могут быть созданы. Единственным назначением абстрактных классов является “вынесение за скобки” общих свойств их потомков.
15.5 Реализация виртуальных функций
Виртуальные функции реализуются с использованием механизма позднего связывания, который заключается в следующем. Для каждого класса, имеющего виртуальные функции, транслятор строит таблицу виртуальных методов (vtable), которая хранит адреса виртуальных функций. Для любого класса в иерархии наследования адрес некоторой виртуальной функции имеет одно и то же смещение в vtable.
Каждый объект класса с виртуальными функциями содержит скрытый указатель vptr на таблицу виртуальных методов класса. Компилятор автоматически вставляет в начало конструктора код, который инициализирует vptr объекта.
Вызов виртуальной функции происходит через vtable, на которую указывает vptr объекта, делающего вызов. Адрес вызываемой функции определяется не во время трансляции (раннее связывание), а во время выполнения программы (позднее связывание). Это позволяет из метода go( ), унаследованного от базового класса обратиться к методу draw( ), определенному в производном классе.
15.6 Полиморфизм
Тот факт, что однажды созданный транслятором код вызывает различные функции, произвел глубокое впечатление на программистов и был назван ими полиморфизмом. Выбор вызываемой функции зависит от того, на какую таблицу виртуальных методов указывает vptr объекта, а это определяется тем, конструктор какого класса инициализировал объект.
Вопросы
1. Как вызвать конструктор предка из конструктора наследника?
2. Пусть элемент х определен в базовом классе с ключом protected, базовый класс наследуется с ключом private. Каков уровень доступа к элементу х в классе-наследнике?
3. Как инициализировать константный элемент класса?
4. Для чего нужны виртуальные методы?
5. Почему конструктор не бывает виртуальным?
6. Зачем нужны абстрактные классы?
7. Что содержит таблица виртуальных методов?
8. Каков механизм позднего связывания?
