C++虚函数重写计算多图形面积时所有结果返回1的问题
问题描述
使用C++ virtual与override关键字实现多态,计算矩形、菱形、三角形、圆形的面积时,所有图形的面积返回值恒为1;即使在main函数中尝试给矩形传入参数调整面积计算输入,输出仍显示所有图形面积为1,异常输出内容如下:
My figure type is My area is 1 My figure type is Triangle My area is 1 My figure type is Circle My area is 1 My figure type is Rhombus My area is 1
问题原始代码:
#include <iostream> #include <string> #include <cmath> using namespace std; class Figure { protected: double x; double y; string type; public: Figure(double m_x, double m_y) : x{ m_x }, y{ m_y } {}; virtual double area(double x, double y) { return 0; }; Figure(double m_x, double m_y, double x = 0, double y = 0) { m_x = x; m_y = y; } virtual void Print() const final; Figure(const Figure& obj); Figure() {}; }; class Rectangle : public Figure { public: Rectangle(double x, double y) { this->x = x; this->y = y; type = " Rectangle"; double area(); } double area(double x, double y) override { return x * y; } Rectangle() {}; }; class Triangle : public Figure { public: Triangle(double x, double y) { this->x = x; this->y = y; type = " Triangle"; double area(); } double area(double x, double y)override { return x * y / 2; } Triangle() {}; }; class Circle : public Figure { public: Circle(double x, double y) { this->x = x; this->y = y; type = " Circle"; double area(); } double area(double x, double y)override { return pow(x, 2) * 3.14; } Circle() {}; }; class Rhombus : public Figure { public: Rhombus(double x, double y) { this->x = x; this->y = y; type = " Rhombus"; double area(); } double area(double x, double y)override { return x * y / 2; } Rhombus() {}; }; void Figure::Print() const { cout << " My figure type is" << type << " My area is " << &Figure::area; } int main() { Rectangle rectangle; rectangle.area(5.4,6.2); rectangle.Print(); Triangle triangle(4.5,5.3); triangle.Print(); Circle circle(6.6, 8.8); circle.Print(); Rhombus rhombus(3.4,5.4); rhombus.Print(); }
错误原因
代码存在多处语法和逻辑错误,直接导致输出异常:
Print函数中输出面积的写法完全错误:&Figure::area是取基类area成员函数的指针,不是调用多态方法计算面积。C++中输出成员函数指针时会隐式转换为bool类型,非空指针转换结果恒为true,输出时固定显示为1,这是所有面积返回1的直接原因。- 基类
Figure的构造函数冲突、逻辑错误:同时定义了二参构造、带默认参数的四参构造、无参构造,其中四参构造的赋值方向写反,把形参m_x/m_y赋值给了默认值为0的局部参数x/y,根本没有给类的成员变量赋值;另外声明了拷贝构造函数但没有实现,本身就会触发链接错误。 - 所有派生类构造函数内写的
double area();是无效的函数声明,不是调用成员方法,没有任何实际作用。 main中创建矩形对象时调用了无参构造,没有给长宽成员变量赋初始值;单独调用rectangle.area(5.4,6.2)得到的返回值没有被存储或使用,完全不影响Print的输出结果。area接口设计不合理:类内部已经存储了计算所需的x/y成员变量,不需要再给area方法传参,既违背封装逻辑,也容易出现传参错误,例如圆形面积计算只需要半径,原接口强制传两个参数,第二个参数完全无效。
修复后代码
针对以上问题调整后可正常运行的代码如下:
#include <iostream> #include <string> #include <cmath> using namespace std; class Figure { protected: double x; double y; string type; public: // 统一构造逻辑,清理冗余冲突的构造声明 Figure(double m_x = 0, double m_y = 0, string m_type = "") : x(m_x), y(m_y), type(m_type) {}; // 无参虚函数,直接读取成员变量计算,支持多态调用 virtual double area() const { return 0; }; virtual void Print() const final; }; class Rectangle : public Figure { public: Rectangle(double length, double width) : Figure(length, width, "Rectangle") {} double area() const override { return x * y; } }; class Triangle : public Figure { public: Triangle(double base, double height) : Figure(base, height, "Triangle") {} double area() const override { return x * y / 2; } }; class Circle : public Figure { public: Circle(double radius) : Figure(radius, 0, "Circle") {} double area() const override { return pow(x, 2) * 3.1415926; } }; class Rhombus : public Figure { public: Rhombus(double diag1, double diag2) : Figure(diag1, diag2, "Rhombus") {} double area() const override { return x * y / 2; } }; void Figure::Print() const { cout << " My figure type is " << type << " My area is " << area() << endl; } int main() { // 创建对象时直接传入计算所需参数,不使用无参构造生成未初始化对象 Rectangle rectangle(5.4,6.2); rectangle.Print(); Triangle triangle(4.5,5.3); triangle.Print(); Circle circle(6.6); circle.Print(); Rhombus rhombus(3.4,5.4); rhombus.Print(); return 0; }
内容的提问来源于stack exchange,提问作者Larrythelobster
相关产品推荐
相关产品推荐

