What you have here is a problem related to "Separation of Concerns". The "Vehicle" concept has a few basic operations some of which you identify, for example "Accelerate". Now the implementation of "Accelerate" is dependent on certain parameters, such as maximum torque, brake-horsepower etc...
These should should be encapsulated outside of the vehicle... but why? Well because they the Vehicle represents a concept, not an implementation. Accelerating will use an engine in the same manner, no matter what that type of car involved. let me use a real-world example:
A McClaren F1 is a Vehicle, in fact it is a car, which contains an engine, has a chassis, has some tyres and suspension etc...
A Volkswagon Golf GTI is a Vehicle, in fact it is a car, which contains an engine, has a chassis, has some tyres and suspension etc...
The user will drive one car in the exact same manner as another car, even if it has hugely different sets of component parts. The user does not need to even be aware of most of the details. This is why you need to separate out your Vehicle concept from the implementation details that are encapsulated by the specific components of your Vehicle.
You should do the same for your "Brakes" as well, and you should inject the Engine and Brakes into the Vehicle at construction (look up Dependency Injection).
Now for colour: I would recommend that you place this at the top level of your class hierarchy, in the Vehicle abstract class. It is something that applies to all classes of vehicles, and is used in the same way by all, and does not affect any implementation. It should be set via the constructor probably, with a repaint
function offered for changing it (once the necessary fees are passed to the Garage via the SalesPoint of course!).
So the class in the end might look like this...
class Vehicle
{
private:
std::unique_ptr<Engine> engine;
std::unique_ptr<Brake> brakes; // same for "Suspension", "Chassis" etc...
VehicleColour colour; // An enum defined here or elsewhere.
public:
Vehicle( std::unique_ptr<Engine> engine, std::unique_ptr<Brake> brakes, VehicleColour colour)
: this->engine(std::move(engine)),
this->brakes(std::move(brakes)),
this->colour(colour) {
}
virtual void Start(const Key& key) {
engine->ignition( key );
brakes->disengage();
}
virtual void Break( BreakPattern pattern ) {
engine->setThrottlePosition( NO_THROTTLE );
brakes->engage( pattern ); // e.g. SIMPLE_HARMONIC, or SLAM... brakes may have ABS or not but you don't need to know
}
virtual void Accelerate() {
brakes->disengage();
engine->setThrottlePosition( TO_THE_METAL );
}
};
Using it:
std::unique_ptr<Brake> absBrakes( new VwAbsDiskBrakes() );
std::unique_ptr<Engine> fastEngine( new TurboV8( FOUR_LITRE ) );
Vehicle hotrod( absBrakes, fastEngine, RED );
hotrod.start();
hotrod.accelerate();
It uses the components via their interfaces, so it doesn't need to know specifics. The sub-classes of Vehicle then do not need to worry about anything that is not Vehicle specific. You will only need a subclass of Vehicle if there is a vehicle that does not fit your generic concept a vehicle (for example if there is a vehicle out there with no brakes).