编写一个基类shape,在此基础上派生出point类,rectangle类和circle类,并从rectangle派生出正方形square类。要求能够实现它们基本的二维平面几何图形功能,如二维空间坐标
时间: 2023-05-31 15:19:08 浏览: 191
### 回答1:
这是一个编写基类Shape,上面派生出生Point类、Rectangle类和Circle类,并且Rectangle类派生出正方形Square类的问题。要求能够实现它们基本的二维平面几何能力,如二维空间坐标等。
### 回答2:
程序的设计思路:首先,定义一个基类shape,包含某些关于二维图形的属性和方法。然后,派生出point、rectangle和circle类作为基类的子类,它们可以继承基类中的一些属性和方法,也可以自己添加新的属性和方法。最后,从rectangle中派生出包含特定属性的正方形square类,它可以继承rectangle类中的大部分属性和方法,同时具有独特的正方形属性和方法。
首先,我们定义基类shape:
class shape
{
protected:
double x,y;
public:
shape(double ix,double iy) //构造函数
{
x = ix;
y = iy;
}
virtual double area() = 0; //虚函数,用于计算面积
virtual void draw() = 0; //虚函数,用于绘图
double getX() {return x;} //获取x坐标
double getY() {return y;} //获取y坐标
};
在基类shape中,我们定义了一个构造函数,用于初始化每个图形的坐标x和y;定义了一个纯虚函数area(),用于计算图形的面积(由于每个图形面积的计算方法不同,所以要在每个子类中重新实现);定义了一个纯虚函数draw(),用于绘图(由于绘图方法不同,也要在每个子类中重新实现);定义了两个获取坐标的函数。
接下来,我们来定义point类:
class point: public shape
{
public:
point(double ix, double iy): shape(ix,iy) {} //构造函数
double area() {return 0;} //计算面积(一个点的面积为0)
void draw() {cout<<"Drawing point at ("<<x<<","<<y<<")"<<endl;} //绘图
};
可以看到,point类继承了shape类,并在构造函数中初始化x和y坐标,在area()函数中,我们重新定义了计算面积的方法,因为一个点的面积为0;在draw()函数中,我们重写了绘图方法。
接着就是rectangle类的定义:
class rectangle: public shape
{
protected:
double width,height;
public:
rectangle(double ix,double iy,double w,double h): shape(ix,iy) //构造函数
{
width = w;
height = h;
}
double area() {return width*height;} //计算面积
void draw() {cout<<"Drawing rectangle at ("<<x<<","<<y<<"), width = "<<width<<", height = "<<height<<endl;} //绘图
double getWidth() {return width;} //获取宽度
double getHeight() {return height;} //获取高度
};
和point类一样,rectangle类也继承了shape类,并在构造函数中初始化x、y坐标、宽度和高度。在area()函数中,我们重新定义了计算面积的方法;在draw()函数中,我们重写了绘图方法,并把宽度和高度加上了输出。最后,我们定义了两个获取宽度和高度的函数。
circle类:
class circle: public shape
{
protected:
double radius;
public:
circle(double ix,double iy,double r):shape(ix,iy)
{
radius = r;
}
double area() {return 3.14*radius*radius;} //计算面积(圆的面积公式)
void draw() {cout<<"Drawing circle at ("<<x<<","<<y<<"), radius = "<<radius<<endl;} //绘图
double getRadius() {return radius;} //获取半径
};
circle类和rectangle类类似,继承了shape类,也有自己的构造函数。在area()函数中,我们重新定义了计算面积的方法,利用圆的面积公式计算圆的面积。在draw()函数中,我们重写了绘图方法,并把半径加上了输出。最后,我们定义了一个获取半径的函数。
最后是square类:
class square: public rectangle
{
public:
square(double ix,double iy,double s):rectangle(ix,iy,s,s) {} //构造函数
double getSide() {return width;} //获取边长
};
square类从rectangle类中派生而来,因此我们要用rectangle的构造函数来初始化x、y坐标和宽度、高度,但是由于正方形的宽和高相等,所以我们直接将width和height定义为s即可。在getSide()函数中,我们定义了获取边长的函数,因为正方形的边长和宽度一样。
最后,我们在main()函数中测试一下:
int main()
{
point p(1,1);
rectangle r(2,2,3,4);
circle c(1,2,5);
square s(3,4,6);
p.draw();
r.draw();
c.draw();
s.draw();
return 0;
}
输出结果:
Drawing point at (1,1)
Drawing rectangle at (2,2), width = 3, height = 4
Drawing circle at (1,2), radius = 5
Drawing rectangle at (3,4), width = 6, height = 6
可以看到,point、rectangle、circle、square都成功创建并绘制。这就是一个简单的基于基类shape的二维平面几何图形类的实现。
### 回答3:
首先,我们需要编写基类shape,它应该包含基本的二维平面几何图形的属性和方法,例如位置信息、尺寸、周长、面积等。由于我们需要从基类派生出其他几个类,因此需要使用虚函数来实现多态性。以下是一个可能的shape基类的代码:
```cpp
class shape {
public:
virtual double area() const = 0; // 计算面积
virtual double perimeter() const = 0; // 计算周长
virtual void move(double dx, double dy) = 0; // 移动图形
virtual void draw() const = 0; // 绘制图形
virtual double distance(const shape&) const = 0; // 计算两个图形之间的距离
virtual ~shape() {} // 虚析构函数
protected:
double x, y; // 图形的位置信息
};
```
接着,我们需要从基类派生出point类、rectangle类和circle类。point类代表一个点,rectangle类代表一个矩形,circle类代表一个圆形。以下是这三个类的可能的实现:
```cpp
class point : public shape {
public:
point(double x = 0, double y = 0) : x(x), y(y) {}
double area() const override { return 0; }
double perimeter() const override { return 0; }
void move(double dx, double dy) override { x += dx; y += dy; }
void draw() const override { std::cout << "point(" << x << ", " << y << ")\n"; }
double distance(const shape& s) const override {
const point* other = dynamic_cast<const point*>(&s);
if (other) {
double dx = x - other->x;
double dy = y - other->y;
return sqrt(dx * dx + dy * dy);
}
return -1.0; // 错误:参数类型不匹配
}
private:
// 点的位置信息
};
class rectangle : public shape {
public:
rectangle(double x, double y, double w, double h) : x(x), y(y), w(w), h(h) {}
double area() const override { return w * h; }
double perimeter() const override { return 2 * (w + h); }
void move(double dx, double dy) override { x += dx; y += dy; }
void draw() const override { std::cout << "rectangle(" << x << ", " << y << ", " << w << ", " << h << ")\n"; }
double distance(const shape& s) const override {
const rectangle* other = dynamic_cast<const rectangle*>(&s);
if (other) {
double dx = x - other->x;
double dy = y - other->y;
return sqrt(dx * dx + dy * dy);
}
return -1.0; // 错误:参数类型不匹配
}
protected:
double x, y; // 矩形左上角的坐标
double w, h; // 矩形的宽和高
};
class circle : public shape {
public:
circle(double x, double y, double r) : x(x), y(y), r(r) {}
double area() const override { return M_PI * r * r; }
double perimeter() const override { return 2 * M_PI * r; }
void move(double dx, double dy) override { x += dx; y += dy; }
void draw() const override { std::cout << "circle(" << x << ", " << y << ", " << r << ")\n"; }
double distance(const shape& s) const override {
const circle* other = dynamic_cast<const circle*>(&s);
if (other) {
double dx = x - other->x;
double dy = y - other->y;
return sqrt(dx * dx + dy * dy) - r - other->r;
}
const point* p = dynamic_cast<const point*>(&s);
if (p) {
double dx = x - p->x;
double dy = y - p->y;
return sqrt(dx * dx + dy * dy) - r;
}
const rectangle* r = dynamic_cast<const rectangle*>(&s);
if (r) {
double cx = std::max(r->x, std::min(x, r->x + r->w));
double cy = std::max(r->y, std::min(y, r->y + r->h));
double dx = x - cx;
double dy = y - cy;
return sqrt(dx * dx + dy * dy) - r;
}
return -1.0; // 错误:参数类型不匹配
}
private:
double x, y; // 圆心的坐标
double r; // 半径
};
```
最后,我们需要从rectangle派生出square类。square类代表一个正方形。由于正方形是特殊的矩形,因此我们只需要重写一些需要变化的方法,例如构造函数和set_size()方法。以下是square类的可能的实现:
```cpp
class square : public rectangle {
public:
square(double x, double y, double size) : rectangle(x, y, size, size), size(size) {}
void set_size(double new_size) { size = new_size; w = h = size; }
private:
double size; // 正方形的边长
};
```
现在,我们可以使用这些类来创建二维平面几何图形,并执行基本的操作,例如计算面积、周长、移动图形等等。每个类都实现了基类shape中定义的虚函数,因此可以使用多态性来实现相关的操作。例如:
```cpp
int main() {
point p(0, 0);
rectangle r(-1, -1, 2, 3);
circle c(3, 2, 1);
square s(1, -2, 2);
const shape* shapes[] = {&p, &r, &c, &s};
const int n = sizeof(shapes) / sizeof(shapes[0]);
for (int i = 0; i < n; i++) {
std::cout << "area = " << shapes[i]->area() << "\n";
std::cout << "perimeter = " << shapes[i]->perimeter() << "\n";
shapes[i]->move(1, 1);
shapes[i]->draw();
std::cout << "\n";
}
return 0;
}
```
以上代码将创建一个点、一个矩形、一个圆形和一个正方形,并分别打印它们的面积和周长。接着,将所有图形向右上角移动一格,并在屏幕上输出它们的位置信息。这个例子展示了使用基类和派生类的多态性,以及面向对象编程的基本思想。
阅读全文