LINUX.ORG.RU

Подкиньте задачек для студентов про полиморфизм в C++

 


0

2

Надо мне студентам придумать несколько задач на тему наследования, виртуальных функций, интерфейсов. Ничего путного не приходит в голову и не гуглится. Так как есть следующие условия: Не требуется STL, Не требуются сторонние библиотеки (в тч системные), Только консольный ввод-вывод



Последнее исправление: CatsCantFly (всего исправлений: 1)

фурктор, лямбда, замыкание. списки, foreach, map, foldl, foldr. options, монада.

anonymous
()

Разбор контекстно независимой грамматики, с вычислением выражения.

Например - калькулятор.

pon4ik ★★★★★
()
Ответ на: комментарий от anonymous

Плюсую предложение анонима на счет фигур.

Meyer ★★★★★
()

Я бы на экзамене задал бы такие вопросы:

1. Дать определение параметрического полиморфизма. 2. Показать, что в С++ парам. полимормизм отсутствует.

Bobby_
()

любые древовидные иерархии: животные/млекопитающие/приматы/homo sapiens;

классификатор адресов - страна/район/город/улица/дом/квартира;

набор вложенных контейнеров: в сундуке заяц, в зайце утка, в утке яйцо, в яйце игла, в игле смерть Кощея.

MyLord
()
Ответ на: комментарий от anonymous

А делать то с ними чего? В чем задание должно заключаться? Я тоже думал над фигурами, но не придумал никакого практического применения.

CatsCantFly
() автор топика
Ответ на: комментарий от CatsCantFly

А вы точно продюсер преподаватель? Это же классика из учебников - фигуры сами себя рисуют на экране, вычисляют свою площадь и периметр...

MyLord
()
Ответ на: комментарий от MyLord

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

CatsCantFly
() автор топика
Ответ на: комментарий от CatsCantFly

Персонажи для игрушки: лучник, мечник и др. имплементируют ИнтерфейсВрезать, друид, маг и др. имплементируют ИнтерфейсКолдовать. Все персонажи наследуют Персонаж с методами узнатьЗдоровье, двинутьНаСевер и др. Потом попросишь сделать мага-лучника )

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

А если лучник выкинет лук и возьмёт меч? ::operator new(this) Mechnick;?

anonymous
()
Ответ на: комментарий от CatsCantFly

Дык, калькулятор вон выше предлагали. Только упоротый - чтобы мог складывать фигуры и считать площадь суммы и разности (без вывода на экран, заодно дебажить будет адово).

Deleted
()

Какие-нибудь числовые башни со сложными числами (целыми, длинными, рациональными как отношения целых/длинных, комплексные, с фиксированной/плавающей запятой, ...).

vzzo ★★★
()

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

xaizek ★★★★★
()
Ответ на: комментарий от fluorite

Написать рогалик хорошее упражнение.

BRE ★★
()
Ответ на: комментарий от vzzo

Какие-нибудь числовые башни

Ага, и не забыть натуральные и целые сделать отдельными классами.

den73 ★★★★★
()

Так как есть следующие условия: Не требуется STL, Не требуются сторонние библиотеки (в тч системные), Только консольный ввод-вывод

Бред. Использовать сишные массивы стоит только для рассказа об управлении памятью. Наследование должно быть после правила трёх/пяти/нуля. Тем самым, когда пришли к наследованию, то уже должны во всю использовать std::string и std::vector

Наверное, всем понятно, в чём тут проблема. Чтобы пользоваться std::vector, совершенно не обязательно знать, как устроены шаблоны и даже что это такое [Как Яндекс создавал курс по C++, или Почему нам всё пришлось переписать].

ХВАТИТ МУЧИТЬ СТУДЕНТОВ И ОТНИМАТЬ У НИХ ВРЕМЯ! В ИТОГЕ 70% НИЧЕГО НЕ ПОЙМУТ И ЗАКАЖУТ ЛАБЫ НА http://www.cyberforum.ru

Общий интерфейс (тут как раз и рассмотреть правила трёх/пяти/нуля):

  • Класс: стек
  • Реализации: на базе массива, на базе списков.

Пример наследования:

  • Базовый класс: персонаж.
  • виртуальный метод: выбрать для атаки - принимает список противников, которых может увидеть персонаж; возвращает список целей для атаки.
  • Класс мечник: атакует ближайшего противника на расстоянии до 2 метров.
  • Класс лучник: если нет противника ближе чем в 2 в двух метрах, то выбирает до трёх ближайших противников на расстоянии от 5 до 20 метров.

Банда четырёх в действии:

  • Фабрика мечников, с заданными диапазонами характеристики атаки.
  • Фабрика лучников, с заданными диапазонами характеристики атаки и стартовым числом стрел.
  • Фабрика случайных персонажей. Используя шаблон проектирования «Строитель» создать фабрику, на вход которой передаются другие фабрики с весовым коэффициентом. Созданная фабрика должна случайно выбирать какую из переданных фабрик использовать для создания персонажа.
AlexVR ★★★★★
()
Ответ на: комментарий от xaizek

Реализовать класс документа

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

Как раз на этом примере в
https://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Cla...
показано, что наследование тут нафиг не нужно.

anonymous
()
Ответ на: комментарий от anonymous

Ну это же Sean Parent. До понимания того, что он говорит, ещё дорости надо.

rupert ★★★★★
()
Ответ на: комментарий от AlexVR

Бред. Использовать сишные массивы стоит только для рассказа об управлении памятью. Наследование должно быть после правила трёх/пяти/нуля. Тем самым, когда пришли к наследованию, то уже должны во всю использовать std::string и std::vector

наконец я слышу голос разума в этом треде :)

Sahas ★★★★☆
()

Вон как второй анона пост. Функтор и монаду (список, например).

Если упороться, то можно запилить какой-нибудь трансформер данных с гиломорфизмами и схемами. Можно вдохновение тут поискать https://github.com/slamdata/matryoshka/

slaykovsky ★★★
()
Последнее исправление: slaykovsky (всего исправлений: 1)

Я в свое время пробовал давать задачку на написание парсинга аргументов командной строки. С тем, чтобы можно было описывать типы аргументов (т.е. аргумент типа int, типа unsigned short, string и т.д.), обязательность-необязательность и т.д. И, как усложнение, чтобы этот же инструмент мог работать не только с argc/argv, но и мог читать response-файлы (т.е. аргументы, указанные в файле, имя которого задается в командной строке).

Тут есть простор и для интерфейсов, и для наследования. И задача простая, которая на пальцах объясняется. И проверяется это все затем очень просто.

eao197 ★★★★★
()
Ответ на: комментарий от CatsCantFly

Не требуется - не значит, что использовать запрещено. Кто знает - уже использует, это только плюс.

А вот это и плохо. Преподаватель в первую очередь источник новой информации для студента. Сейчас лабораторные по программированию должны проходить по схеме: вот вам репозиторий на bitbucket (или github, но первый для преподавателей даёт неограниченной число связей и приватных репозиториев, что удобно для курсовых/дипломов), клонируете, правите вот такой и такой файлы, потом добавляете то-то и то-то, ..., сдаёте.

Как итог дополнительный фактор контроля самостоятельной работы студентов, т.к. уже после пары лет преподавания курса, понимаешь сколько по времени какой шаг у студента занимает. В добавок можно показать студентам как применяется тестирование кода, как структурировать проект, как использовать системы сборки, как выглядит красивый код, как применять 90 рекомендаций по стилю написания программ на C++ и т.д. Не тратя на это время. Вот тут уже, те кому интересно будут изучать что-то новое и полезное, а для остальных это обычные шаги в лабе, которые они проскакивают. Я уже много лет использую системы контроля версий в лабах со студентами. И не смотря на резко упавший уровень IQ новоиспечённых студентов, ещё не было ни одного человека, не понявшего как пользоваться hg (спасибо unC0Rr, а переходить в лабах на git не хочу, у студентов больше вопросов возникает что да как исправить).

Проблема выбора хороших примеров для наследования решается обзором некоторых из шаблонов проектирования. Без них сейчас рассказывать о наследовании архаично. Зачем мучить студентов квадратиками и собачками? Им это не интересно. А объяснить зачем это программисту - не возможно. Такие примеры были на заре преподавания ООП, сейчас очень многое изменилось.

В качестве развития методики преподавания информатики, прекрасным примером является: https://code.org. Это идеальный ресурс для обучения в младших классах. Среднее звено просело. И это бьёт по знаниям абитуриентов. На выходе из ВУЗа, студент должен знать намного больше, чем было это 10 лет назад. А бороться с латентностью образования должен в первую очередь преподаватель. Т.е. от тебя зависит, с какими новыми и полезными знаниями выйдет студенты, после твоего курса.

AlexVR ★★★★★
()

Пускай пилят свои контейнеры (вектор, список, хэшмапу). Заодно поймут на кой хрен это всё надо.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от AlexVR

Т.е. от тебя зависит, с какими новыми и полезными знаниями выйдет студенты, после твоего курса.

А я всегда думал, что программу курса составляет кафедра? Мало ли что захочет преподаватель, может он фортран только и умеет.

Bobby_
()
Ответ на: комментарий от Bobby_

А я всегда думал, что программу курса составляет кафедра?

  • Преподаватель член кафедры.
  • Преподаватель курса часто является автором/соавтором курса (особенно в последние годы, когда меняются стандарты, под которые переписываются программы).
  • Преподаватель может вносить предложения по изменению программы курса для следующих лет поступления.
  • Программа курса может быть достаточно абстрактной, что бы дать поле для манёвра. Т.к. именно преподаватель должен решать, какие методики применять. А студенты от года в год разные (например в кризисные коды, больше умных студентов остаётся в региональных ВУЗах).
AlexVR ★★★★★
()
Ответ на: комментарий от Bobby_

2. Показать, что в С++ парам. полимормизм отсутствует.

Вы серьезно? Я конечно точного-буквоедного-академического определения не знаю, но оно даже в Си присутствует косвенно - неявное приведение типов, или же преднамеренная техника пользования безтипового указателя. А в плюсах поверх этого перегрузки ф-й и шаблоны. И вот шаблоны вероятно как раз покрывают академическое определение, но а на практике что в си что в си++ по факту есть параметрический полиморфизм

bonta ★★★★★
()

Да блин, пусть, например, реализуют класс рациональных чисел на основе целых.

Заодно узнают и о том, зачем нужна нормальная (каноническая) форма, и как перегружать операторы, и про конструкторы с параметрами и без.

Можно чуть попроще: комплексные числа.

unanimous ★★★★★
()
Ответ на: комментарий от bonta

Параметрическая типизация — это механизм, который позволяет разрабатывать программы (обычно, алгоритмы и структуры данных) безотносительно типов данных, с которыми они работают. На практике применяется два подхода — мономорфизм и параметрический полиморфизм. STL, стандартная библиотека шаблонов C++. Это, пожалуй, наиболее известный пример полиморфизма — наборы универсальных коллекций, работающих с любыми типами. Шаблоны C++ представляют собой пример т.н. мономорфизма. На самом деле, для каждого типа из шаблона компилируется свой класс, который работает только с этим типом. Например, если мы используем шаблонный класс vector<T> дважды, один раз для int, другой раз для long, то будет скомпилировано два класса — vector<int> и vector<long>. Какой из них будет использоваться, будет решено на стадии линковки, в зависимости от типа аргумента. Усматривается прямая аналогия с перегрузкой функций, и это правильно — явления мономорфизма и перегрузки функций относят к общему классу ad-hoc полиморфизмов.

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

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

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

Пример параметрического полиморфизма — generic’и в Java. Класс с generic’ом (обобщенным типом) компилируется только один раз. При этом в байт-код в нужных местах добавляются проверки и приведения типов. Это защищает разработчика от попытки добавить в List<Cat> объект типа Dog, но немного понижает скорость работы. К счастью, такие проверки обычно успешно оптимизируется виртуальной машиной.

Bobby_
()
Ответ на: комментарий от Bobby_

И в чем проблема сделать на C++ параметрический полиморфизм? Будет тоже самое, что в ява. Класс Object, контейнеры принимающие Object. Нужна типизация? Добавь тривиальные обертки-перегрузки в .h файле template<typename T> void Add(T const & val) { AddObj(val); }

Вот тебе и явовские generic-и

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Bobby_

Да, но я предлагаю только шаблоны оберток. AddObj не шаблон, а void AddObj(Object const &o); , и живет в .cpp

Это чисто ява-подход. Диспетчеризация будет в AddObj

Deleted
()
Последнее исправление: Deleted (всего исправлений: 2)
Ответ на: комментарий от Bobby_

Да и вообще, чего я придумываю. Использовать void Add(Object const &o); в паблике, не надо никаких шаблонов. В контейрере храняться объекты-наследники Object

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Bobby_

А я не понял, в чем проблема c реализацией параметрического полиморфизма на основе общего родителя Object? Это же самый наивный подход к созданию либы контейнеров на C++.

Deleted
()
Ответ на: комментарий от Deleted

Еще раз, кто в рантайм будет делать приведение типа и проверку, чтобы пользователь в список котов не смог добавить собаку?

Bobby_
()
Ответ на: комментарий от anonymous

В С++ все проверки делает компилятор, а потом угар и содомия на твоей совести никто ничего тебе проверять не будет.

Bobby_
()
Ответ на: комментарий от Deleted

Я вообще жду, что если язык поддерживает парам. полиморфизм, то все вопросы с типами разруливает сам компилятор, или я не прав?

Bobby_
()
Ответ на: комментарий от Bobby_

Ты правильно и удачно выше расписал про отличия и виды полиморфизмов. Но странно не видишь отличие теоретического определения от реализации в языке. В С++ есть параметрический полиморфизм, он используется вполне определенным образом, это не секрет для разработчиков на C++. Поэтому исходный посыл, с чем я и спорю, на мой взгляд, не верен.

В отличие от упомянутого С#, в C++ можно реально задействовать как и параметрический, так и ad-hoc полиморфизмы. (Ну, перегрузка методов тривиальна и я не её имею ввиду).

Deleted
()

У меня студенты обычно пишут ферму: базовый класс клетка + наследники типа «клетка с курицей», «клетка с коровой» и т.п.

trex6 ★★★★★
()
Ответ на: комментарий от Deleted

dynamic_cast - это антипаттерн. К тому же он тормозной как хрен.

rupert ★★★★★
()

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

Пусть подумают. Может быть даже придут к выводу, что наследование реализаций не всегда подходит, и A is a B не значит, что обязательно нужно наследовать A от B.

red75prim ★★★
()
Последнее исправление: red75prim (всего исправлений: 2)
Ответ на: комментарий от Deleted

При таком подходе можно сказать, что в С++ есть GC? Только он используется определенным образом. Только программист на С++ должен ручками все написать, а не автоматически, как это работает в java.

Bobby_
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.