Предпочитайте конкретные типы иерархиям классов
Причина
Конкретный тип фундаментально проще, чем тип в иерархии классов: его проще разработать, реализовать, использовать, понять, он занимает меньше памяти и работает быстрее. Для использования иерархии нужны веские причины (варианты использования).
Пример
class Point1 {
int x, y;
// ... операции ...
// ... нет виртуальных функций ...
};
class Point2 {
int x, y;
// ... операции, некоторые виртуальные ...
virtual ~Point2();
};
void use()
{
Point1 p11 {1, 2}; // создаём объект на стеке
Point1 p12 {p11}; // копия
auto p21 = make_unique<Point2>(1, 2); // создаём объект в свободной памяти
auto p22 = p21->clone(); // делаем копию
// ...
}
Если класс является частью иерархии, мы (в реальном коде, а не в небольших примерах) должны работать с его объектами через указатели или ссылки. Это означает больше накладных расходов по памяти, больше выделений и освобождений памяти, а также больше накладных расходов во время выполнения из-за косвенных обращений.
Примечание
Конкретные типы могут размещаться на стеке и быть членами других классов.
Примечание
Использование косвенности фундаментально для полиморфных интерфейсов во время выполнения. Накладные расходы на выделение/освобождение памяти при этом необязательны (это просто наиболее распространённый случай). Мы можем использовать базовый класс в качестве интерфейса для объекта производного класса, размещённого в области видимости. Это делается там, где динамическое выделение памяти запрещено (например, в жёсткой реальном времени) и для обеспечения стабильного интерфейса для некоторых видов плагинов.
Контроль
???