我试图了解虚拟函数和C ++中的继承。在下面的示例代码中,我有两个类AreaCube(基类)和SideAreaRatio(派生类)。我试图在派生类中的另一个函数“ ratio ”中调用基类中的虚函数“ area ”。我正在尝试使用基类的实例来实现这一点。但由于某些我不熟悉的原因,我看到生成了奇怪的答案。请在这里告诉我发生了什么!
#include<iostream>
using namespace std;
class AreaCube {
public:
int side;
AreaCube() {};
AreaCube(int s) {
side = s;
}
virtual ~AreaCube() {};
virtual int area() {
cout<< "calling.. " << endl;
int area = side*side*side;
return area;
}
};
class SideAreaRatio:public AreaCube {
public:
SideAreaRatio(int s) {
side = s;
};
~SideAreaRatio() {};
float ratio() {
AreaCube a;
int area = a.area();
cout<< area << endl;
return (side/area);
}
};
int main() {
AreaCube* ac = new AreaCube(2);
cout<< ac->area() << endl;
SideAreaRatio* sar = new SideAreaRatio(4);
cout<< sar->ratio() << endl;
}
预期输出:
calling..
8
calling..
8
0.3333
生成输出:
calling..
8
calling..
-1265467392
0
答案 0 :(得分:2)
您使用默认构造函数创建的a
的新实例AreaCube
,该实例未在实例side
上设置a
的值。此内存不能保证保留任何特定值,当您调用a.area()
时,结果将是未定义的。
有一个简单的解决方法:将AreaCube a;
替换为AreaCube a(side);
,看看你是否得到了正确的行为。或者,您可以避免完全实例化AreaCube
的新实例,只需直接调用基类方法:int area = AreaCube::area()
。请注意,您不需要在此处传递side
,因为基类方法对当前对象的(this
)状态进行操作。
此外,另一个阻止此工作的问题是:当您划分两个int
变量时,它会将结果截断为int
。你需要让它来执行浮点除法:用return (side/area);
替换return (1.0f * size / area);
,一切都应该没问题。
答案 1 :(得分:2)
它没有工作,因为你实际上没有用任何值构造AreaCube
对象,所以当它计算区域时它会给你垃圾(因为side
变量有没有值,如调用默认构造函数所示。)
我认为你想要做的是:
#include<iostream>
using namespace std;
class AreaCube {
public:
int side;
AreaCube() {};
AreaCube(int s) {
side = s;
}
virtual ~AreaCube() {};
virtual int area() {
cout<< "calling.. " << endl;
int area = side*side*side;
return area;
}
};
class SideAreaRatio:public AreaCube {
public:
SideAreaRatio(int s) {
side = s;
};
~SideAreaRatio() {};
float ratio() {
int area = area();
cout<< area << endl;
return (side/area);
}
};
int main() {
AreaCube* ac = new AreaCube(2);
cout<< ac->area() << endl;
SideAreaRatio* sar = new SideAreaRatio(4);
cout<< sar->ratio() << endl;
}
您不需要在派生类中实例化AreaCube
,因为您需要的所有内容都已存在。只需调用area()
方法。
从基类继承时,保留所有成员变量和成员函数,因此除了派生类之外,不需要实例化任何内容。因此,在这种情况下,SideAreaRatio既有side变量又有area()方法
值得一提的是,你并没有真正使用virtual
方法做任何事情。
答案 2 :(得分:1)
在SideAreaRatio
类中,在调用AreaCube
而不初始化{{1}时,使用默认构造函数(AreaCube()
)创建类型为ratio
的新对象该类的成员字段。接下来,继续对仍未定义的side
值进行计算。
答案 3 :(得分:1)
将float ratio()
更改为
float ratio() {
int area = area();
cout<< area << endl;
return (side/area);
}
由于SideAreaRatio
是-a AreaCube
,因此可以直接使用区域功能。
答案 4 :(得分:0)
这里
float ratio() {
AreaCube a;
int area = a.area();
cout<< area << endl;
return (side/area);
}
创建一个使用默认构造函数启动的对象。但是,AreaCube的默认构造函数不执行任何操作。因此,如果您真的想要创建一个新对象,请使用
AreaCube a(side);
代替。
或者你可以打电话
area()
直接不创建AreaCube的新对象,即
float ratio() {
return (side/area());
}
你打电话的原因
area()
直接就是这个方法是在基类中定义的。在这种情况下,即使它没有被定义为虚拟,您仍然可以使用它。你可以尝试看看结果是一样的。
基本上你的代码不是虚函数的正确实现。