Это зависит от ваших целей. Вы можете использовать версию 1, если вы
- Намерены заменить тормоза автомобиля (во время работы)
- Намерен передать Car не шаблонным функциям
Как правило, я бы предпочел версию 1 с использованием полиморфизма времени выполнения, потому что он все еще гибкий и позволяет иметь Car по-прежнему того же типа: Car<Opel>
- это другой тип, чем Car<Nissan>
. Если ваши цели - отличная производительность при частом использовании тормозов, я рекомендую вам использовать шаблонный подход. Кстати, это называется политическим дизайном. Вы предоставляете политику торможения . Пример, потому что вы сказали, что программируете на Java, возможно, вы еще не слишком разбираетесь в C ++. Один из способов сделать это:
template<typename Accelerator, typename Brakes>
class Car {
Accelerator accelerator;
Brakes brakes;
public:
void brake() {
brakes.brake();
}
}
Если у вас много политик, вы можете сгруппировать их в свою собственную структуру и передать ее, например, SpeedConfiguration
, собирающую Accelerator
, Brakes
и некоторые другие. В своих проектах я стараюсь сохранить большую часть кода без шаблонов, позволяя им быть скомпилированными один раз в свои собственные объектные файлы, не нуждаясь в их коде в заголовках, но все же допуская полиморфизм (через виртуальные функции). Например, вы можете захотеть сохранить общие данные и функции, которые не шаблонный код, вероятно, будут вызывать во многих случаях в базовом классе:
class VehicleBase {
protected:
std::string model;
std::string manufacturer;
// ...
public:
~VehicleBase() { }
virtual bool checkHealth() = 0;
};
template<typename Accelerator, typename Breaks>
class Car : public VehicleBase {
Accelerator accelerator;
Breaks breaks;
// ...
virtual bool checkHealth() { ... }
};
Между прочим, это также подход, который используют потоки C ++: std::ios_base
содержит флаги и прочее, которые не зависят от типа char или характеристик, таких как openmode, флаги форматирования и прочее, тогда как std::basic_ios
является шаблоном класса наследует это. Это также уменьшает раздувание кода за счет совместного использования кода, который является общим для всех экземпляров шаблона класса.
Частное наследство?
В целом следует избегать частного наследства. Это очень редко полезно, и сдерживание - лучшая идея в большинстве случаев. Распространенный случай, когда верно обратное, когда размер действительно важен (например, строковый класс на основе политики): Оптимизация пустого базового класса может применяться при выводе из пустого класса политики (просто содержащего функции).
Чтение Использование и злоупотребление Наследством Хербом Саттером.