简体   繁体   中英

C++ Passing an Object to Another Object From Another Class

I am trying to write this program using base classes and derived classes where there is a truck with a maximum capacity of 8 tons. Then this truck is loaded with 1.5 tons of apple and then loaded with 0.5 tons of kiwi. This would then diminish the amount of tons remaining to 6.5 when the apples are loaded and then to 6 when the kiwis are loaded. This is an assignment and in the main function I see they are calling the function loadCargo as follows truck.loadCargo(Apple()) , I am unsure of what this is accomplishing. Please take a look at the complete code:

#include <iostream>
#include <string>
using namespace std;

class Cargo{
public:
    double c = 0;
    double getAmount(){
        return c;
}
};


class Apple : public Cargo{
public:
    double c = 1.5;
    double getAmount(){
        return c;
}
};

class Kiwi : public Cargo{
public:
    double c = 0.5;
    double getAmount(){
        return c;
        }
}; 

class Truck {
    double maxCapacity = 8;
public:
    void loadCargo(Cargo cargo){
    maxCapacity = maxCapacity - cargo.getAmount();
}
        void printInfo(){
            cout << maxCapacity << " tons remaining" << endl;
        }
};


int main() {
    Truck truck;
    truck.printInfo();

        truck.loadCargo(Apple());
        truck.printInfo();

        truck.loadCargo(Kiwi());
        truck.printInfo();
}

I thought that truck.loadCargo(Apple()) would pass an object of Apple to the object cargo. Therefore when loadCargo is called, it would access the getAmount function in Apple class and not in class Cargo but that is not happening. The output should be:

8 tons remaining
6.5 tons remaining
6 tons remaining

But currently it is the following since it just using the getAmount from the Cargo class:

8 tons remaining
8 tons remaining
8 tons remaining

EDIT: Since this is an assignment I cannot change anything in the main function or in the line that has void loadCargo(Cargo cargo) .

First, you need to make your getAmount() function virtual:

class Cargo{
public:
    double c = 0;
    virtual double getAmount(){
        return c;
    }
};

Then, your derived classes will override the getAmount() function with their version.

Without the virtual keyword, if your function accepts a parameter of type Cargo , it will just used the Cargo::getAmount() function.

Second, you need to pass your object into by const-reference, like this:

class Truck {
    double maxCapacity = 8;
public:
    void loadCargo(const Cargo& cargo){
        maxCapacity = maxCapacity - cargo.getAmount();
    }
    ...

This will ensure that your cargo object inside the loadCargo function will refer to an Apple object or a Kiwi object. By passing by value, you're copying your Apples object into a Cargo object, and you fall over the slicing problem .

ETA: You would also need to change your getAmount() function to const like this:

//                 vvvvv
double getAmount() const {
    return c;
}

Since you mention you cannot change your Truck class , you can do this by setting the value of c in your Cargo class constructor. Like this:

class Cargo{
public:
    double c;

    // Constructor, using an initializer list to set the value of `c`.
    Cargo(const double c_value) :
        c(c_value) {
    }

    double getAmount(){
        return c;
    }
};

Then, in your Apple and Kiwi classes, set the value of c inside the constructor, like this:

class Apple : public Cargo{
public:
    // Set the Cargo's mass in the Apple constructor...
    Apple() :
        Cargo(1.5) {
    }

    // getAmount() function removed.
};

Finally, remove the getAmount() functions from your Apple and Kiwi classes (but KEEP for the Cargo class).

Final Note

Please bear in mind that passing Cargo by value will always suffer from the Slicing Problem (see link above) and should be avoided, though because your Apple and Kiwi objects don't have any member variables, it will still work for your assignment. If inheritance is how your instructor wanted this to work, then passing Cargo by value into loadCargo(Cargo cargo) is bad C++ practice . This doesn't impact your assignment, but if you wish to take C++ seriously, bear this in mind for the future!

When you make this call:

truck.loadCargo(Apple());

You are indeed passing an Apple to truck . However, the declaration of loadCargo takes a Cargo object:

void loadCargo(Cargo cargo)

This slices the Apple and now you simply have a Cargo object that you call getAmount on. This returns 0, and so the maxCapacity doesn't change.

There are various ways to fix this, but the simplest would be to make loadCargo a template, so that it can accept any type without first converting it to a Cargo object:

template<typename Fruit>
void loadCargo(Fruit cargo)

Here's a demo .


Note that for this implementation, so long as Apple and Kiwi have the same member functions as expected of a Cargo object, you can avoid inheriting from a base class entirely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM