-2

I'm working on a project to handle an inventory of cars. There is a base Vehicle class and a derived AdvancedVehicle class. I am running into an issue with my serialize function which is meant to be a virtual function. It seems that whenever the function is called by either the base or derived class, it only runs the base serialize function. Attached is both the Vehicle and AdvancedVehicle class definitions and implementations.

/////////////////////////////// VEHICLE //////////////////////////////////
class Vehicle{
    friend ostream& operator<< (ostream& os, const Vehicle v) {
            v.Serialize(os);
            return os;
    }
public:
    Vehicle() = delete;
    Vehicle(string model, size_t year, float price) {
        m_model = model;
        m_year = year;
        m_baseprice = price;
        m_owner = NULL;
    }
    Vehicle(string model, size_t year, float price, const Client* owner) {
        m_model = model;
        m_year = year;
        m_baseprice = price;
        m_owner = new Client("");
        *m_owner = *owner;
    }
    Vehicle(const Vehicle& otherVehicle) {
        m_model = otherVehicle.m_model;
        m_year = otherVehicle.m_year;
        m_baseprice = otherVehicle.m_baseprice;
        m_owner = NULL;
    }
    Vehicle& operator= (const Vehicle& otherVehicle) {
        m_model = otherVehicle.m_model;
        m_year = otherVehicle.m_year;
        m_baseprice = otherVehicle.m_baseprice;
        m_owner = new Client("");
        *m_owner = *otherVehicle.m_owner;
        return *this;
    }
    void setPrice(float price) {
        m_baseprice = price;
    }
    void SetOwner(const Client* owner) {
        m_owner = new Client("");
        if(owner)
        {
            *m_owner = *owner;
        }
    }
    string GetModel() const { return m_model; }
    size_t GetYear() const { return m_year; }
    virtual float GetPrice() const { return m_baseprice; }
    Client* GetOwner() const { return m_owner; }
    virtual void Serialize(ostream& os) const {
        os << m_year << " ";
        os << m_model << " ";
        os << m_baseprice << " ";
        if(m_owner != NULL)
        {
            os << *m_owner << endl;
        }
    }
protected:
    string m_model;
    size_t m_year;

private:
 float m_baseprice;
 Client* m_owner;
};



/////////////////////////// ADVANCEDVEHICLE ///////////////////////////////
class AdvancedVehicle : public Vehicle{
    friend ostream& operator<< (ostream& os, const AdvancedVehicle AV) {
        AV.Serialize(os);
        return os;
    }
public:
    AdvancedVehicle() = delete;
    AdvancedVehicle(string model, size_t year, float price, vector<Sensor> sensors, const Client* owner):Vehicle (model, year, price){
        m_model = model;
        m_year = year;
        SetOwner(owner);
        setPrice(price);
        for(auto i = sensors.begin(); i != sensors.end(); i++)
        {
            int j = 0;
            AddSensor(sensors[j]);
            j++;
        }
    }
    AdvancedVehicle(string model, size_t year, float price, vector<Sensor> sensors):Vehicle (model, year, price){
        m_model = model;
        m_year = year;
        SetOwner(NULL);
        setPrice(price);
        for(auto i = sensors.begin(); i != sensors.end(); i++)
        {
            int j = 0;
            AddSensor(sensors[j]);
            j++;
        }
    }
    AdvancedVehicle(const AdvancedVehicle& otherAV):Vehicle( otherAV) {
        m_model = otherAV.m_model;
        m_year = otherAV.m_year;
        m_finalprice = otherAV.m_finalprice;
        SetOwner(NULL);
        for(auto i = otherAV.m_sensors.begin(); i != otherAV.m_sensors.end(); i++)
        {
            int j = 0;
            AddSensor(otherAV.m_sensors[j]);
            j++;
        }
    }
    AdvancedVehicle& operator=(const AdvancedVehicle& otherAV) {
        m_model = otherAV.m_model;
        m_year = otherAV.m_year;
        setPrice(otherAV.GetPrice());
        SetOwner(otherAV.GetOwner());
        for(auto i = otherAV.m_sensors.begin(); i != otherAV.m_sensors.end(); i++)
        {
            int j = 0;
            AddSensor(otherAV.m_sensors[j]);
            j++;
        }

        return *this;
    }
    void AddSensor(Sensor addedSensor) {
        m_sensors.push_back(addedSensor);
        m_finalprice += addedSensor.GetPrice();
    }
    virtual float GetPrice() const { return m_finalprice; }
    virtual void Serialize(ostream& os) const {
        os << m_year << " ";
        os << m_model << " ";
        os << m_finalprice << " ";
        if(GetOwner() != NULL)
        {
            os << GetOwner() << " ";
        }
        for(auto i = m_sensors.begin(); i != m_sensors.end(); i++)
        {
            os << &i << " ";
        }
        os << endl;
    }

private:
    vector<Sensor> m_sensors;
    float m_finalprice;
};

1 Answers1

2

Your program is suffering from the object slicing problem. The operator<< takes a Vehicle object by value. This means a new Vehicle object is copy-constructed from the argument passed to the operator. The new object is a Vehicle, not an AdvancedVehicle, even if what was passed to the operator was an AdvancedVehicle. The object is said to have been sliced and this is why the base version of the Serialize() function is called.

To address this, you should modify the operator<< overload to take a Vehicle by reference (Vehicle&). This will eliminate the copy and the slicing.

TypeIA
  • 16,916
  • 1
  • 38
  • 52