我在.HPP文件中创建了一个带有虚函数的可派生类,然后在类的.CPP文件中给它一个默认的返回值。接下来,我创建了一个继承后一个派生类的类,并重载了它的虚函数,给它一个新的返回值。但是,返回值并不总是相同(默认返回值或重载返回值)。有人可以帮我修复我的代码或找到问题。感谢。
注意:我提供示例代码,我相信这足以显示问题。
#include <iostream>
#include <sstream>
using std::cout;
using std::ostream;
class Fruit;
class Apple;
class Fruit
{
public:
int Type;
Fruit();
~Fruit();
Fruit(int = 0);
virtual const int getVal() const;
};
class Apple : public Fruit
{
public:
Apple();
~Apple();
const int getVal() const;
};
Fruit::Fruit() : Type(0) {}
Fruit::~Fruit() {}
Fruit::Fruit(int type) : Type(type) {}
//const int Fruit::getVal() const { return 0; } //Uncommenting this results in function //always returning ZERO; even in Apple::getVal().
const int Fruit::getVal() const { return Type; }
Apple::Apple() : Fruit(1) {}
Apple::~Apple() {}
const int Apple::getVal() const { return Type; }
ostream& operator<<(ostream& a, Fruit b)
{
return a << b.getVal();
}
int main(int *argc, char **argv)
{
cout << Apple() << "\n\n";
#ifdef _WIN32
system("pause");
#endif
return 0;
}
答案 0 :(得分:6)
您遇到的问题是object slicing。由于您的Apple
正按值传递到operator<<
,因此只会复制对象的Fruit
部分。因此,当调用getVal
时,会在基类Fruit
而不是Apple
上调用它。
要解决此问题,请确保在处理基类时使用引用(或指针)而不是值。例如,此处的修复方法是简单地使用const Fruit&
而不只是Fruit
。
ostream& operator<<(ostream& a, const Fruit& b)
{
return a << b.getVal();
}
正如维基百科条目所说,这个问题在C ++中出现,因为“按值分配不是多态的”。
答案 1 :(得分:2)
ostream& operator<<(ostream& a, Fruit b)
此代码使用定义为Fruit(const Fruit&);
的构造函数构造Fruit类型的新对象。
Apple
是Fruit
,因此它可以用作Fruit复制构造函数的参数,但Fruit
复制构造函数会定期Fruit
您提供的Fruit的子类,因此您将获得常规Fruit
。这有点令人困惑地称为“切片”。
相反,您可能希望定义运算符以获取const引用,因此不使用复制构造函数。像这样,ostream& operator<<(ostream& a, const Fruit& b)
我还建议在水果类的私有部分(未实现)中声明复制构造函数和赋值运算符,这样你就不会再意外地犯这个错误了
答案 2 :(得分:0)
你正在与切片问题发生冲突。您的operator<<
正在获取该对象的副本,而不是对该对象的引用。由于你没有定义一个拷贝构造函数,编译器为你做了一个,它做错了。
答案 3 :(得分:0)
快速跳出的一件事是你没有通过指针调用getVal(),并且因为你的operator<<
采用Fruit而不是Apple,它有效地切掉了对象的派生部分。请尝试使用Fruit&
作为operator<<
的参数。
答案 4 :(得分:0)
改变这个:
ostream& operator<<(ostream& a, Fruit b)
{
return a << b.getVal();
}
对此:
ostream& operator<<(ostream& a, const Fruit& b)
{
return a << b.getVal();
}
它应该工作。
在您的实施中,您正在构建Apple的全新Fruit实例。 所以调用Fruit :: getVal()。