Classes and class hierarchies
C.137
Используйте `virtual`-базы для избежания слишком общих базовых классов
Причина
Позволяет разделить общие данные и интерфейс. Чтобы избежать помещения всех общих данных в единственный конечный базовый класс.
Пример
struct Interface {
virtual void f();
virtual int g();
// ... нет данных здесь ...
};
class Utility { // с данными
void utility1();
virtual void utility2(); // точка настройки
public:
int x;
int y;
};
class Derive1 : public Interface, virtual protected Utility {
// переопределяем функции Interface
// Возможно, переопределяем виртуальные функции Utility
// ...
};
class Derive2 : public Interface, virtual protected Utility {
// переопределяем функции Interface
// Возможно, переопределяем виртуальные функции Utility
// ...
};
Выделение Utility имеет смысл, если многие производные классы разделяют значительные «детали реализации».
Примечание
Очевидно, пример слишком «теоретический», но найти небольшой реалистичный пример сложно. Interface является корнем иерархии интерфейсов, а Utility — корнем иерархии реализаций. Вот немного более реалистичный пример с объяснением.
Примечание
Часто линеаризация иерархии является лучшим решением.
Контроль
Помечать смешанные иерархии интерфейсов и реализаций.