C++ 几何层次结构、类向上转换和继承
Posted
技术标签:
【中文标题】C++ 几何层次结构、类向上转换和继承【英文标题】:C++ Geometry hierarchy, Class upcasting and inheritance 【发布时间】:2020-12-17 23:55:10 【问题描述】:我正在做一个理解类的项目,但遇到了困难。如果您对我的语法有任何建议,请让我知道我哪里出错了,因为我对编程还是很陌生,但我的问题是与类继承有关。 (包括 A、C 和 D,但完成得相当好)。
我的项目:
A.从点类开始...覆盖
B.创建一个基类 Shape。 Shape 将包含计算面积、周长和取点值的函数,以创建一个封装给定形状的框。这些将被派生类重载。创建一个显示所有相关信息(名称、面积、周长和封装框)的 display() 函数。
C.通过制作圆形、方形、三角形来构建形状的层次结构......添加默认和自定义构造函数,其参数使用正确数量的点对象初始化形状。我觉得我也很满意。
D.在 main() 中创建每个实例。圆半径 = 到 23,每个正方形边 = 25,三角形边 = 10、20 和 30(非常平坦的三角形,面积 = 0)。定义每个包含原点 (0, 0)。显示所有信息。我觉得我已经完成了这个(减去显示功能)。
我的问题是(以及我在哪里苦苦挣扎),“我如何正确地从基类(形状)创建/访问函数以返回有意义的信息。”
我是否真的只是将它们全部设为虚拟,因为某些类没有与其他类相同的信息? (比如 Area() 和 Circumference()?)
#include <iostream>
#include <cmath>
using namespace std;
class Point
public:
int x, y;
Point()
x = 0;
y = 0;
Point(int x, int y): x(x), y(y) // constructor
friend ostream& operator<<(ostream& out, const Point number) //Involves ostream to output the numbers
out << "(" << number.x << ", " << number.y << ")"; //that were input into the x and y values of Point.
return out;
friend Point operator+(Point first, Point second) //Takes two mathematical vectors and tells the compiler
Point add; // to add the x values together and the y values together
add.x = first.x + second.x;
add.y = first.y + second.y;
return add;
friend Point operator-(Point first, Point second) // same as above but with subtraction.
Point subtract;
subtract.x = first.x - second.x;
subtract.y = first.y - second.y;
return subtract;
;
class Shape
protected:
float height, width;
public:
Shape()
height = 0;
width = 0;
Shape(float h, float w)
height = h;
width = w;
/*
int Display()
//Do something..... Create a display function
return 0;
int BoundingBox()
//Do something again......
return 0;
*/
virtual float Area() const = 0;
virtual float Circumference() const = 0;
virtual ~Shape() ;
;
class Circle: public Shape
Point center;
float radius;
public:
Circle(): Shape() ;
Circle (Point p1, float r) //Takes center point object, and given radius.
center = p1;
radius = r;
virtual float Area() const override // Calculates circle area
return(M_PI * radius * radius);
virtual float Circumference() const override // Calculates circumference
return(float (M_PI * 2 * radius));
virtual ~Circle() ;
;
class Square: public Shape
Point first, second, third, fourth;
public:
Square(): Shape() ;
Square(Point p1, Point p2, Point p3, Point p4) // Takes four point arguments and initializes them
first = p1;
second = p2;
third = p3;
fourth = p4;
height = second.x - first.x; //calculates the height and width from points
width = third.y - first.y;
virtual float Circumference() const override
return 0; //Errors without the return statement
virtual float Area() const override // Calculates area by measuring the difference between given points
return(height * width);
virtual ~Square() ;
;
class Triangle: public Shape
Point first, second, third;
public:
Triangle(): Shape() ;
Triangle(Point p1, Point p2, Point p3) // Takes three point arguments and initializes them
first = p1;
second = p2;
third = p3;
height = third.y - first.y;// due to the nature of the question, this only works for flat triangles.
width = second.x - first.x;
virtual float Circumference() const override
return 0; //Errors without the return statement
virtual float Area() const override
return ((height * width) / 2);
virtual ~Triangle() ;
;
int main()
Point p1(0, 0), p2(25, 0), p3(0, 25), p4(25, 25), p5(20, 0), p6(30, 0);
Circle c1 (p1, 23); // Circle with origin (0, 0) and a radius of 23
Square s1 (p1, p2, p3, p4); // Square with 4 points and the origin
Triangle t1 (p1, p5, p6); // Extraordinarily flat triangle with origin
cout << c1.Circumference() << endl;
cout << s1.Area() << endl;
cout << t1.Area() << endl;
在这一点上,我感到有点迷失了方向,我确信我在此过程中要么犯了几个错误,要么只是犯了几个错误,但无论如何,我不明白。任何建议将不胜感激!
编辑:我已经更新了我的代码,以包括包含虚拟解构函数、删除 getheight 等...语句以及将虚拟添加到派生函数的建议
【问题讨论】:
你到底为什么要使用friend
作为公共方法?
因为我不这样做时整个程序都会中断...
【参考方案1】:
当您使用继承时,请确保在所有继承类以及基类中使用虚拟析构函数。
如果您想进行进一步的专业化,您继承的虚函数也将受益于标记virtual
和override
。
您正在覆盖继承的函数,但它们的作用与原始函数相同,例如GetHeight()
。这有点违背了继承这些功能的意义。如果它们没有被覆盖,它们也不需要是虚拟的。
您的派生类将受益于显式调用基类的构造函数。如果您不提供要调用的特定构造函数,它将调用默认构造函数,这可能是也可能不是您想要的行为 - IMO 始终提供您想要的基类构造函数更安全!
举个例子:
class Shape
protected:
float height, width;
public:
Shape()
height = 0;
width = 0;
Shape(float h, float w)
height = h;
width = w;
virtual float Area() const = 0;
virtual float Circumference() const = 0;
virtual ~Shape() ;
;
class Circle: public Shape
Point center;
float radius;
public:
Circle() : Shape() ;
Circle (Point p1, float r) : Shape()
// Note you may wish to set the height and width here!
//Takes center point object, and given radius.
center = p1;
radius = r;
virtual float Area() const override // Calculates circle area
return(M_PI * radius * radius);
virtual float Circumference() const override // Calculates circumference
return(float (M_PI * 2 * radius));
virtual ~Circle() ;
;
【讨论】:
好的,谢谢!我已经更改了我的代码,并且收到了与我对正方形和三角形圆周的不良修复之前相同的错误。 /usr/bin/ld: /tmp/ccgy05RH.o: 在函数Square::Square(Point, Point, Point, Point)': TMA3Question3.cpp:(.text._ZN6SquareC2E5PointS0_S0_S0_[_ZN6SquareC5E5PointS0_S0_S0_]+0x2f): undefined reference to
vtable for Square' /usr/bin/ld: /tmp/ccgy05RH.o: 在函数Square::~Square()': TMA3Question3.cpp:(.text._ZN6SquareD2Ev[_ZN6SquareD5Ev]+0x13): undefined reference to
vtable for Square'
/usr/bin/ld: /tmp/ccgy05RH.o: 在函数Triangle::Triangle(Point, Point, Point)': TMA3Question3.cpp:(.text._ZN8TriangleC2E5PointS0_S0_[_ZN8TriangleC5E5PointS0_S0_]+0x2b): undefined reference to
vtable for Triangle' /usr/bin/ld: /tmp/ccgy05RH.o: 在函数Triangle::~Triangle()': TMA3Question3.cpp:(.text._ZN8TriangleD2Ev[_ZN8TriangleD5Ev]+0x13): undefined reference to
Triangle'collect2 的 vtable:错误:ld 返回 1 个退出状态
已更新以反映您的建议! (再次感谢!)以上是关于C++ 几何层次结构、类向上转换和继承的主要内容,如果未能解决你的问题,请参考以下文章