Выступление Шона Пэрента, Наследование — это базовый класс of evil, говорит, что полиморфизм — это не свойство типа, а скорее свойство того, как он используется. Как правило, не используйте наследование для реализации интерфейсов. Среди многих преимуществ этого — девиртуализация классов, которые имеют виртуальные функции только потому, что они реализуют интерфейс. Вот пример:
class Drawable
{
public:
virtual void draw() = 0;
};
class DrawA : public Drawable
{
public:
void draw() override{//do something}
};
class UseDrawable
{
public:
void do(){mDraw->draw();}
Drawable* mDraw;
};
Здесь вместо UseDrawable
, требующего, чтобы mDraw
был Drawable*
, вы могли бы использовать класс со стертым типом, который может обернуть любой класс, реализующий член с именем draw
. Итак, что-то вроде boost::type_erasure::any
с соответствующим определением. Таким образом, DrawA
не нужно наследовать от Drawable
- полиморфизм действительно был требованием UseDrawable
, а не свойством DrawA
.
Я пытаюсь реорганизовать код, следуя этому принципу. У меня есть абстрактный класс ModelInterface
и два конкретных класса ModelA
и ModelB
, унаследованных от ModelInterface
. Следуя совету Шона, имеет смысл не навязывать ModelA
и ModelB
иерархию наследования, а просто использовать стирание типов в тех местах, где требуется класс, удовлетворяющий концепции, смоделированной ModelInterface
.
Теперь моя проблема заключается в том, что большинство мест в моем коде, которые в настоящее время используют ModelInterface
, также делают это, создавая соответствующий объект на основе файла конфигурации времени выполнения. В настоящее время фабрика будет new
подбирать соответствующий объект и возвращать ModelInterface*
. Если я реорганизую код, чтобы использовать концепцию стирания типов (скажем, что-то вроде boost::type_erasure::any<implement ModelInterface>
) в этих местах кода, как мне создать такие объекты во время выполнения? Должны ли классы ModelA
и ModelB
по-прежнему быть классами с поддержкой RTTI? Или я могу как-то изготовить их на заводе и использовать без информации RTTI?
(С RTTI я могу иметь абстрактный класс, скажем, FactoryConstructible
, и использовать dynamic_cast<void*>
для получения окончательного типа.)
boost::any
для этой цели не подходит (по крайней мере, как интерфейс). Я думаю, вы должны вернуть некоторыйModel
из вашей фабрики, в которой хранится некий объект с стертым типом, выполняющий концепцию ModelInterface. ЗатемModel
похож наDocument
, который использует Шон Пэрент (хотя он хранит не коллекцию, а один объект). - person dyp   schedule 05.10.2014Model
и возвращаете объектModel
по значению. - person dyp   schedule 05.10.2014