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.