我正在尝试使用基类和派生类编写此程序,其中有一辆最大载重量为8吨的卡车。然后,这辆卡车装有1.5吨苹果,然后装有0.5吨猕猴桃。这样,当装载苹果时,剩余的吨数将减少到6.5,而当装载猕猴桃时,将减少到6的吨数。这是一个分配,在主函数中,我看到他们正在按loadCargo
的方式调用函数truck.loadCargo(Apple())
,但我不确定这样做是什么。请查看完整的代码:
#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();
}
我认为truck.loadCargo(Apple())
会将Apple对象传递给对象货物。因此,在调用loadCargo
时,它将访问Apple类而不是Cargo类中的getAmount
函数,但是这没有发生。输出应为:
8 tons remaining
6.5 tons remaining
6 tons remaining
但是由于它仅使用Cargo类中的getAmount
,因此目前如下:
8 tons remaining
8 tons remaining
8 tons remaining
编辑:由于这是一项分配,因此我无法在主函数或具有void loadCargo(Cargo cargo)
的行中进行任何更改。
答案 0 :(得分:2)
首先,您需要将.on
函数设为虚拟:
getAmount()
然后,您的派生类将使用其版本覆盖class Cargo{
public:
double c = 0;
virtual double getAmount(){
return c;
}
};
函数。
如果没有getAmount()
关键字,则您的函数接受类型为virtual
的参数,它将仅使用Cargo
函数。
第二,您需要通过const-reference将对象传递给它,如下所示:
Cargo::getAmount()
这将确保class Truck {
double maxCapacity = 8;
public:
void loadCargo(const Cargo& cargo){
maxCapacity = maxCapacity - cargo.getAmount();
}
...
函数内的cargo
对象将引用loadCargo
对象或Apple
对象。通过传递值,您将Kiwi
对象复制到Apples
对象中,并且掉到了slicing problem上。
ETA:您还需要像下面这样将Cargo
函数更改为getAmount()
:
const
由于您提到无法更改Truck类,因此可以通过在Cargo类构造函数中设置// vvvvv
double getAmount() const {
return c;
}
的值来实现。像这样:
c
然后,在您的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;
}
};
和Apple
类中,在构造函数中设置Kiwi
的值,如下所示:
c
最后,从您的class Apple : public Cargo{
public:
// Set the Cargo's mass in the Apple constructor...
Apple() :
Cargo(1.5) {
}
// getAmount() function removed.
};
和getAmount()
类中删除Apple
函数(但对于Kiwi
类保留KEEP)。
最终通知
请记住,按值传递货物将始终遭受切片问题(请参见上面的链接),因此应避免使用,尽管因为您的Cargo
和Apple
对象没有任何成员变量,它将仍然适用于您的分配。如果您的老师希望继承是这样工作的,那么按值将Kiwi
传递到Cargo
是不好的C ++实践。这不会影响您的分配,但是如果您希望认真对待C ++,请记住这一点,以备将来之需!
答案 1 :(得分:1)
拨打电话时:
truck.loadCargo(Apple());
您的确将Apple
传递给truck
。但是,loadCargo
的声明带有一个Cargo
对象:
void loadCargo(Cargo cargo)
这将切片Apple
,现在您只需拥有一个调用Cargo
的{{1}}对象。这将返回0,因此getAmount
不变。
有多种解决方法,但是最简单的方法是将maxCapacity
用作模板,以便它可以接受任何类型而无需先将其转换为loadCargo
对象:
Cargo
这里是demo。
请注意,对于此实现,只要template<typename Fruit>
void loadCargo(Fruit cargo)
和Apple
具有与Kiwi
对象相同的成员函数,就可以避免完全从基类继承。 / p>