So i'm learning about composition and i think i got the idea right, but let me know if im wrong, I need to get the part name so i can output it in the operator<< overload function. Static casting didnt seem to work. Since a vehicle has a part, i did Part engine, in the vehicle class only since the other classes inherit it, or do i need to put it in the other classes too?
Also, one thing i was wondering, If say I make an airplane class, if i make a Boeing737Max class thats empty, is it even worth creating that class? or is it better to just do Airplane Boeing737Max and create it that way? I guess if the max has special features that other airplanes dont then it would warrant doing that but what if it's empty? should you just create one for future proofing in case you will add stuff to it? or is it just the interface of a specific type of airplane thats worth having?
Anyway I hope i did this right, i've been following tutorials and courses and guides, just wanted to get some input. I did a little function overloading too along with composition and inheritance.
Boeing 737 max "is-a" airplane, and an airplane "is-a" vehicle, but part is not, but a vehicle "has-a" part(multiple) so I assume that is correct, thats what I was shown at least. The more you move down the inheritance hierarchy the more specialized or specific the classes get. Just want to make sure I got this stuff down before moving on to polymorphism.
Any improvements that could be made or things im doing wrong, I would greatly appreciate being pointed out.
Also one last question, in each class that inherits from vehicle, I have to retype all the vehicle classes constructor argument list stuff, is there a simpler way to just copy it over without having to retype it all and then just type out the variables for that class?
Something like:
Code:Airplane(Vehicle::Vehicle, float elevationCeiling): Vehicle::Vehicle, mElevationCeiling(elevationCeiling){}
Something like that. I think if the language doesnt support that it would be great to have as you have to update every class when you add a variable to the base classes argument list. This way it's almost like a variable, you can have it in tons of spots but only need to update one location.
Code:#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
using std::string;
class Part
{
public:
Part() = default;
Part(const string& name): mName(name)
{}
friend std::ostream& operator<<(std::ostream& os, const Part& part)
{
os << part.GetPartName() << endl;
return os;
}
string GetPartName() const { return mName; }
private:
string mName{ "Part Name" };
};
class Vehicle
{
public:
Vehicle
(
const string& type,
const string& name,
float maxSpeed,
//In MPH
float maxFuelCapacity,
//In Gallons
float fuelUsedPerMinute,
float maxRange,
Part& engine
) : mType(type),
mName(name),
mMaxSpeed(maxSpeed),
mMaxFuelCapacity(maxFuelCapacity),
mFuelUsePerMinute(fuelUsedPerMinute),
mMaxRange(maxRange),
mEngine(engine)
{}
string GetType() const { return mType; }
string GetName() const { return mName; }
float GetMaxSpeed() const { return mMaxSpeed; }
float GetMaxFuelCapacity() const { return mMaxFuelCapacity; }
float GetFuelUsedPerMinute() const { return mFuelUsePerMinute; }
float GetMaxRange() const { return mMaxRange; }
void StartVehicle();
private:
string mType{ "Vehicle Type" }; //Airplane, automobile, etc.
string mName{ "Vehicle Name" };
float mMaxSpeed{ 0.0 };
float mMaxFuelCapacity{ 0.0 }; //In gallons
float mFuelUsePerMinute{ 0.0 }; //How much fuel is consumed
float mMaxRange{ 0.0 }; //How far this vehicle can travel
Part mEngine;
};
void Vehicle::StartVehicle()
{
cout << "Engine Started" << endl;
}
class Airplane : public Vehicle
{
public:
Airplane
(
const string& type,
const string& name,
float maxSpeed,
float maxFuelCapacity,
float fuelUsedPerMinute,
float maxRange,
Part& engine,
float elevationCeiling
)
: Vehicle
(
type,
name,
maxSpeed,
maxFuelCapacity,
fuelUsedPerMinute,
maxRange,
engine
), mElevationCeiling(elevationCeiling)
{}
using Vehicle::StartVehicle;
void StartVehicle();
float GetelevationCeiling() const { return mElevationCeiling; }
private:
float mElevationCeiling{ 0.0 };
};
void Airplane::StartVehicle()
{
cout << "Perform pre-flight checks" << endl;
cout << "Ready for takeoff" << endl;
}
//If a class like this has no variables is it worth making a class for instead of just doing Airplane Boeing737Max?
class Boeing737Max final : public Airplane
{
public:
Boeing737Max
(
const string& type,
const string& name,
float maxSpeed,
float maxFuelCapacity,
float fuelUsedPerMinute,
float maxRange,
Part& engine,
float elevationCeiling
)
: Airplane
(
type,
name,
maxSpeed,
maxFuelCapacity,
fuelUsedPerMinute,
maxRange,
engine,
elevationCeiling
)
{}
friend std::ostream& operator<<(std::ostream & os, const Boeing737Max& max)
{
os << "Vehicle Name: " << max.GetName() << endl;
os << "Vehicle type: " << max.GetType() << endl;
os << "Max Speed: " << max.GetMaxSpeed() << " MPH" << endl;
os << "Max Fuel Capacity: " << max.GetMaxFuelCapacity() << " gallons" << endl;
os << "Fuel Used Per Minute: " << max.GetFuelUsedPerMinute() << endl;
os << "Max Range: " << max.GetMaxRange() << " Miles" << endl;
//os << static_cast<const Part&>(max);
return os;
}
using Airplane::StartVehicle;
void StartVehicle();
};
void Boeing737Max::StartVehicle()
{
cout << GetName() << " ready for takeoff" << endl;
}
int main()
{
Part LEAP1B("CFM International LEAP-1B");
Boeing737Max Max("Airplane", "Boeing 737 Max", 521.0f, 6875.0f, 0.0f, 3521.0f, LEAP1B, 41000.0f);
cout << Max << endl;
Max.StartVehicle();
}