Программирование на языке C++

Описание

Курс расчитан на студентов, владеющих синтаксисом хотя бы одного из "стандартных" структурных языков программирования (C, Pascal, Fortran, и т.п.). Это значит, что в нем не будет рассказываться об основных понятиях: переменных, функциях, условных операторах, циклах и.т.д. В этом плане, кроме того, предполагается, что слушатели знакомы с основным синтаксисом языка C. Если это предположение ошибочно, то в первые 2 недели будет прочитан очень плотный (2 лекции + 2 практических занятия в неделю) вводный курс по синтаксису.

В неделю читается 2 академических часа лекций и проводится 2 часа практики. Приблизительные темы практических занятий выделены курсивом. Для практики необходим класс с компьютерами (по 1 на студента) и доской. Необходимое программное обеспечение на компьютерах — Ubuntu (или любой другой современный дистрибутив Linux), gcc, Eclipse.

Программа на первый семестр

  1. Языки C и C++
    С++ — (почти) надмножество C. Возможность написания эффективных программ на C++. Сложности программирования на C++: прямая работа с памятью. Размер языка C++, невозможность изложения всего в одном курсе.
    Превращение кода в программу: компиляция и линковка. Что проверяется при компиляции, а что — при сборке. Структура программы на C/C++: файлы кода и заголовочные файлы. Что можно поместить в заголовочные файл, а что — нельзя. Макросы — очень плохая идея. Макросы для защиты от повторного включения заголовочного файла. Зависимости между частями программы. Makefile.
    Практика: Написание простой программы, состоящей из нескольких файлов кода и заголовочного файла. Написание Makefile. Target 'clean'.
  2. Как работает программа
    Во что превращается этот код в исполняемом файле. Структура исполняемой программы. Раздел кода, раздел данных. Использование памяти в работающей программе. Стек и куча. Как передаются параметры функции. Где оказываются локальные переменные.
    Практика: Управляющие структуры языка C. Процесс компиляции. Если окажется, что все достаточно просто — преобразование .c в .S.
  3. Указатели и ссылки
    Передача параметра с помощью указателя. Взятие адреса переменной и, наоборот, значения по адресу. Неинициализированные указатели. Нулевой указатель. Потенциальные проблемы при использовании указателей. Ссылки. Сходство с ссылок с указателями и их отличия. Как хранятся ссылки.
    Практика: Передача параметров с помощью указателей и ссылок. Получить seg.faults
  4. Распределение памяти в куче
    Язык C: malloc/free. Язык C++: new/delete и new[]/delete[]. Почему нужны 2 набора операторов. Потенциальные проблемы. Вопросы производительности. Двумерные массивы.
    Практика: Заработать переполнение памяти. Выделить место под двумерный массив разными способами. Сравнить время работы разных способов выделения памяти.
  5. С++ как "С с удобными структурами"
    Идея инкапсуляции. Конструктор и деструктор. Класс "самоуправляющегося" массива. Автоматический вызов деструктора. Об опасности неожиданного завершения программы. Еще о различиях malloc/free и new/delete. Конструктор копирования. Проблемы с присваиванием объектов. Как запретить присваивание.
    Практика: Класс массива, класс двумерного массива.
  6. Строки в C. Ввод и вывод в C и C++
    Массивы и указатели. Строки. Конеч строки. Строковые константы. Операции со строками.
    Дескриптор файла, FILE. Что происходит пр открытии закрытии файла. Буфферизация, flush/fflush. Стандартные файлы stdin, stdout, stderr. Практика: Потоковый вывод на экран (std::out, std::err, без объяснения смысла).
    Практика: Написать на основе FILE свой поток (без операторов).
  7. "Внутренности" класса
    Поля и методы. Ограничение прав доступа к членам класса. Все поля должны быть private. Почему это удобно. Проблемы с производительностью. inline. Какие методы стоит делать public? Принцип "всегда целого" объекта. Что нужно оптимизировать программисту, а что сделает за него компилятор. Примеры оптимизации: никогда не вызывать функцию дважды. Code conventions.
    Практика: Рациональные числа, приведение к общему знаменателю.
  8. Инициализация и const
    Потенциальные проблема: неинициализированные переменные. Возможности инициализации в конструкторе. Другая проблема — случайное изменение переменных. Решение: константные поля. Констатные методы. Константное возвращаемое значение. "Заразность" const. Идея возвращения значения по ссылке. возможность создания "парных" методов const/не-const. this.
    Практика: Класс массива, класс-обертка для FILE.
  9. Слово static
    Статические "глобальные" переменные. Статические локальные переменные. Статические функции. Статические члены класса. Необходимость инстанциации статических полей. Code conventions.
    Практика: Глобальные константы. Адреса глобальных и статических переменных. Подсчет числа вызовов, количества экземпляров класса.
  10. Некоторые возможности C++, о которых стоит упомянуть namespace. mutable. перегрузка операторов. перегрузка оператора присваивания. не стоит злоупотреблять перегрузкой (кроме оператора присваивания).
    Практика: Рациональные числа с операторами.
  11. Наследование
    Идея "расширения" типа. Проблемы с копированием. Неявное приведение типов. protected. Подробнее об ограничениях, которые накладывают права доступа. friend'ы. Сравнение с другими языками (Java). Невозможность полной защиты в C++. Права доступа как средство "самоограничения" для программиста.
    Практика: Добавить к потоку вывода удобные доп. возможности для вывода чего-нибудь специального (например, рациональных чисел).
  12. Перегрузка и переопределение. Полиморфизм
    Перегрузка имен методов. Не стоит злоупотреблять перегрузкой. Перегрузка конструкторов. Сложные правила выбора из перегруженных методов. Статическая и динамическая типизация: разные подходы в разных языках.
    Перегрузка и переопределение — разные слова. Виртуальные методы. Чисто виртуальные методы. Таблица виртуальных функций. Снова о статической и динамической типизации. Виртуальные деструкторы. Порядок построения таблицы. Опасность вызова виртуальных методов из конструктора. Почему это не запрещено синтаксически?
    Практика: Добавить к потоку вывода удобные доп. возможности. Вызов виртуального метода из конструктора.
  13. Умные указатели
    Написание класса scoped_ptr (без шаблонов). Задача: то же самое для массива. Возможные расширения идеи: auto_ptr. Возможные расширения идеи: считающие ссылки.
  14. Идеи шаблонов
    scoped_ptr на шаблонах. Общая идея шаблонов. Шаблоны функций и классов. Вывод шаблонных параметров из аргументов функций. Компиляция шаблонов.

Программа на второй семестр

  1. Шаблоны, часть 1
    Шаблоны функций и классов. Вывод шаблонных параметров из аргументов функций. Шаблоны конструкторов и обычных методов. Компиляция шаблонов. Почему их нужно определять в заголовочных файлах. Аргументы шаблонов по умолчанию. Полезность typedef.
  2. Шаблоны, часто 2
    Специализация шаблонов. Отличие специализации от перегрузки. Частичная специализация шаблонов. Нетиповые шаблонные параметры. Использование зависимых имён (использование typename).
  3. STL, последовательные контейнеры
    Общие идеи STL. Итераторы вместо индексов. Работа с последовательными контейнерами (vector, list, deque).
  4. STL, ассоциативные контейнеры
    Работа с ассоциативными контейнерами (map, set). Версии контейнеров с неуникальными элементами. Задание упорядочивания для пользовательских типов.
  5. STL, адаптеры и итераторы
    Контейнерные адаптеры. Категории итераторов. Итераторы в обратном направлении. Требования к итераторам. Как написать свой итератор. Идея iterator_traits.
  6. STL, алгоритмы
    Требования алгоритмов к элементам и последовательностям. Алгоритмы для произвольных последовательностей. Алгоритмы для упорядоченных последовательностей. Алгоритмы изменяющие последовательности. Другие категории алгоритмов. Как написать собственный алгоритм. Как специализировать алгоритм для конкретного типа итераторов/элементов. Создание собственных функторов.
  7. Указатели на функции и члены классов
    Указатели на функции. Указатели на методы. Указатели на члены данных. Использование указателей на функции в качестве функторов. Пример использование указателей на методы - паттерн Listener.
  8. Пространства имён
    Определение пространств имён. Глобальное пространство имён. Директивы using (2 формы). Поиск имён. Поиск Кёнига (ADL). Поиск имён при наследовании.
  9. Исключения
    Концепция исключений. Стандартные классы исключений. Спецификация исключений. Стратегии обработки исключений. Почему не стоит бросать встроенные типы. Исключения в конструкторе. Исключения в списке инициализации. Недопустимость исключений в деструкторах.
  10. Гарантии безопасности исключений
    Гарантии безопасности исключений. В каких случаях мы можем обеспечить строгую гарантию исключений. Использование swap для безопасности. Использование auto_ptr для обеспечения безопасности исключений. Проектирование с учётом исключений.
  11. Преобразования в стиле С++ и RTTI
    Преобразования в стиле C++: static_cast, const_cast, reinterpret_cast, dynamic_cast. Преимущества над преобразованиями в стиле C. В каких случаях преобразование в стиле C приводит к ошибкам (множественное наследование).
  12. Библиотека Boost
    Библиотеки умных указателей, строковые алгоритмы, итераторы. Использование утилитарных библиотек для обеспечения кросс-платформенности. Библиотеки для создания функторов: bind и lambda.
Последние две лекции носят скорее "обзорный" характер. Этими две лекциями можно пожертвовать в случае нехватки времени.
  1. Метапрограммирование на C++
    SFINAE и enable_if. Определение наследование одного класса от другого. Алгебраические структуры на шаблонах. Поддержка метапрограммирования в Boost.
  2. Стандарт C++11
    Изменения, которые вступили в силу в новом стандарте.

Материалы курса