Первый вопрос: почему вы хотите иерархию наследования более двух уровней?Наиболее частой иерархией наследования, безусловно, будет абстрактный базовый класс и один уровень классов, которые вытекают из него.(По крайней мере, когда деривация используется для реализации наследования ОО - нередко использование деривации C ++ для других целей.)
Существует два частых паттерна, где встречается более глубокая иерархия наследования.Первое происходит, когда вы расширяете интерфейс;на практике нет большой разницы между этим и производным от единственной абстрактной базы, и было бы ошибкой выводить класс, обеспечивающий реализацию в любом случае.Во-вторых, реализация настраивается с использованием шаблона метода шаблона.И в этом случае вы действительно хотели бы отобразить в нем функции реализации final
: любой, унаследованный от этого класса, должен реализовывать только новые виртуальные функции, используемые для определения настройки;в противном случае вы, вероятно, не сможете гарантировать все необходимые инварианты.