C语言面向对象(下)
上一节当中,我们介绍了面向对象的三大特性中的其中两个特性:封装、继承。这一节中,我们将介绍多态这一特性。
单纯理论上的讨论可能比较难以理解,为了能够让我们的讨论能够落地到实际中,我们以绘制各种图形为背景,展开对多态这一特性的讨论。
1. 绘制图形
现在,我们有3种图形,它们分别为:
- 矩形
- 圆形
- 三角形
我们把这3种图形均看做对象,这些图形对象,分别需要有哪些属性呢?
- 矩形:左上角坐标、右下角坐标
- 圆形:圆心x坐标、圆心y坐标、半径
- 三角形:三个顶点坐标
现在,我们用代码分别实现这几个对象。
struct Rect {
int left;
int top;
int right;
int bottom;
};
struct Circle {
int x;
int y;
int r;
};
struct Triangle {
POINT p1;
POINT p2;
POINT p3;
};
为了能够在屏幕上绘制这些图形,每个图形都设置一个名为draw
的方法。
struct Rect {
int left;
int top;
int right;
int bottom;
void (*draw)(struct Rect *);
};
struct Circle {
int x;
int y;
int r;
void (*draw)(struct Circle *);
};
struct Triangle {
POINT p1;
POINT p2;
POINT p3;
void (*draw)(struct Triangle *);
};
分别实现3个不同的绘制函数。
绘制矩形:
调用easyx
中的rectangle
函数,传入左上角坐标与右下角坐标。
void drawRect(struct Rect* r)
{
rectangle(r->left, r->top, r->right, r->bottom);
}
绘制圆形:
调用easyx
中的circle
函数,传入圆心坐标与半径。
void drawCircle(struct Circle* c)
{
circle(c->x, c->y, c->r);
}
绘制三角形:
调用easyx
中的line
函数,分别绘制点p1
到p2
的线段,p2
到p3
的线段,以及p3
到p1
的线段。
void drawTriangle(struct Triangle *t)
{
line(t->p1.x, t->p1.y, t->p2.x, t->p2.y);
line(t->p2.x, t->p2.y, t->p3.x, t->p3.y);
line(t->p3.x, t->p3.y, t->p1.x, t->p1.y);
}
下面,分别写3个初始化函数,用于给对象中的函数指针draw
进行赋值。
void initRect(struct Rect* r)
{
r->draw = drawRect;
}
void initCircle(struct Circle* r)
{
r->draw = drawCircle;
}
void initTriangle(struct Triangle* r)
{
r->draw = drawTriangle;
}
现在,准备工作都做好了,我们开始绘制这些图形吧。
int main()
{
initgraph(800, 600);
setaspectratio(1, -1);
setorigin(400, 300);
setbkcolor(WHITE);
setlinecolor(BLACK);
cleardevice();
struct Rect r = {-200, 200, 200, 0};
struct Circle c = {0, 0, 100};
struct Triangle t = { {0, 200}, {-200, 0}, {200, 0} };
initRect(&r);
initCircle(&c);
initTriangle(&t);
r.draw(&r);
c.draw(&c);
t.draw(&t);
getchar();
closegraph();
return 0;
}
创建一个800 * 600
的绘图窗体,设置x
轴正方向为从左到右,y
轴正方向为从下到上。将原点坐标从窗体左上角更改为窗体中心。设置背景颜色为白色,描边颜色为黑色,并使用背景色刷新整个窗体。下面分别声明矩形、圆形、三角形三个对象,并将需要的属性初始化。之后,三个对象分别调用各自的init
函数,为对象内的函数指针赋值。完成准备工作后,即可使用对象+点+方法的形式,调用各自的draw
方法绘制图形了。