вторник, 30 июля 2013 г.

ПМО ИУС — ООП — Наследование и полиморфизм

Наследование уже изучалось после прохождения 3-й работы и усваивания Google Test Framework. Таким образом, первые основные три темы, которые должны были введены быть в курс как можно быстрее для того, чтобы в каждой из работ потом повторятся — проведены.

Вместе с наследованием изучалась перегрузка операторов. Полиморфизм без наследования изучать сложно, а перегрузка операторов потом пригождается при изучении STL.

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

При перегрузке операторов обязательно использование унарного и бинароного операторов и демонстрация работы с ними.

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

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

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

Все это проверяется в Google Test. Как и следовало ожидать, так как функция переносится в наследник, то все тесты ломаются, так как базовый класс уже создать нельзя в силу его абстрактности. В связи с этим чинятся тесты (что полезно — что-то изменилось, нужно привести в порядок тесты). И далее тестируется в том числе и новая функция.

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

Фокус держится на контроле тестирования и на адекватности понимания полиморфизма. Т.е. важно понимать то, что можно работать с многими разными типами не вникая в более низкие детали реализации.

Подробности

Слайды, слайды.

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

Наследование может быть в несколько уровней. Кроме того, оно может быть множественное и очень разное.

При сборке иерархии наследования прежде всего ориентируются на тех типах с точки зрения абстрагирования, которые были нами выделены. Если мы можем объединить по какому-либо существенному признаку несколько объектов, то может быть целесообразным эту общее собрать в одном базовом классе. С точки зрения абстрагирования это могут быть как данные, так и код. (примеры для иерархий) Выполняя объединение получается так, что это дает нам возможность не переписывать общие части в каждом из наследников, а использовать одну и ту же функциональность несколько раз, при этом держа её под определенной абстракцией с конкретными границами. Кроме того, мы можем оперировать элементами более высокого уровня (например мы можем посчитать периметр для любой двумерной фигуры, или объем для любой трехмерной).

Как это делается в С++. Демонстрация повторного использования кода и данных.

Изменение доступа при наследовании в C++. По умолчанию делаем public.

Размещение данных в памяти и как может произойти срезка.

Синтаксис конструирования объектов иерархии. Порядок вызова конструкторов и деструкторов.

Доступ к одноименным функциям в рамках одной иеррархии наследования.

Множественное наследование (как так получается, контроль одного базового класса компилятором С++).

Перегрузка функций в С++. Одно имя, разный интерфейс. Выбор интерфейса исходя из контекста. Преимущества такого подхода по сравнению с зоопарком разноименных функций.

Перегрузка операторов. Оператор — та же функция, которая вызывается, только синтаксис немного другой. Бинарные и унарные операторы.