Проблем с преобразованием типов и порядком вызова методов нет, поэтому никаких усложнений с виртуализацией, использующихся в шаблоне для С++, не требуется.
Более того, не требуется и сам шаблон! Можно пойти и другим путём несложной и безопасной реструктуризации: извлечь существующие в неявном виде интерфейсы элементов документа в явные определения и обследовать в методе сбора статистики передаваемый объект на предмет реализации классами интерфейсов. Например, if (elemType is IParagraph), is IImage, is IFormula и т. д. Тогда можно обойтись вообще без отражения.
Наконец, существует и другое специфичное для C++ решение: реализовать аналогичную иерархию с заданной виртуальной операцией и, далее, используя множественное наследование, «подмешать» эти реализации к существующей иерархии, используя в дальнейшем только полученные классы-миксты.
Весьма элегантное решение на основе
Итого на простом примере имеем целый букет решений вместо одного шаблонного, из которых можно выбирать оптимальный. Попытавшись однажды объяснить подобное программисту, видимо, несколько увлёкшемуся шаблонами, я не встретил понимания.
Несколько позднее я наткнулся в магазине на книгу с названием, претендующим на звание наиболее абсурдного из встречавшихся. Оно звучало как «Thinking in patterns». В переводе на русский язык – «Мыслить шаблонно». Ещё недавно привычка шаблонно мыслить считалась в инженерном сообществе признанием ограниченности специалиста, наиболее пригодного для решения типовых задач с 9 утра до 6 вечера. Теперь не стесняются писать целые книжки о том, как научиться шаблонному мышлению…Думать головой
Серия коротких заметок была задумана, как некий противовес механистическому подходу к программированию, пропагандируемому различными учебниками шаблонов. Потому что думать надо не шаблонами, а головой. Начнём с того, что кажется очевидным.
Обобщение
Откажитесь от термина «наследование», который искажает смысл действий. Мы обобщаем. Обобщение (наследование) реализации или интерфейсов – весьма неоднозначный механизм в объектно-ориентированном программировании, его применение требует осторожности и обоснования.
ОСНОВНОЕ ПРАВИЛО
Обобщаемые классы должны иметь сходную основную функциональность.
Например, если два или более класса:
• порождают объекты, реализующие близкие интерфейсы;
• занимаются различающейся обработкой одних и тех же входных данных;
• предоставляют единый интерфейс доступа к другим данным, операциям или к сервису.