项目概览
本课属于 Coddy C 学习旅程的“面向对象编程”单元。第 44 课,共 61 课。
挑战
简单让我们先创建基础的 Shape 结构体,为 Shape Drawer 项目打好基础:它是一个接口,通过函数指针定义任何形状都能执行的操作。
你将创建两个文件来搭建这个多态系统:
shape.h:在这里定义核心接口。首先,为Shape结构体创建前向声明。然后定义两种函数指针类型:DrawFunc:接收一个const Shape*参数,不返回任何值AreaFunc:接收一个const Shape*参数,并返回一个double
Shape结构体本身,其中包含两个函数指针:draw(类型为DrawFunc)和area(类型为AreaFunc)。这个结构体只是一个接口。它不包含任何特定形状的数据,只包含行为。main.c:创建一个简单的测试形状,演示你的接口可以正常工作。实现两个函数:test_draw:打印Drawing test shapetest_area:返回42.0
Shape实例,将它连接到这两个测试函数,然后通过接口调用这两个函数。将面积结果以一位小数的形式打印出来。
输出应展示函数指针可以正常工作:
Drawing test shape
Area: 42.0为什么需要前向声明?你可能会想,为什么 typedef struct Shape Shape; 会出现在结构体完整定义的前面。这是因为 DrawFunc 和 AreaFunc 的参数类型中引用了 const Shape*,但在文件的那个位置,编译器还没有看到完整的结构体定义。前向声明告诉编译器:“存在一个名为 Shape 的结构体”,这就足以让你使用指向它的指针。完整定义会在后面出现。只要结构体需要引用自身(直接引用或通过函数指针引用),这种写法在 C 中就很常见。
这里的关键在于,Shape 并不了解圆形或矩形。它只知道任何形状都必须能够 draw 自身并计算自己的 area。在接下来的课中,你将创建具体形状,让它们包含这个基础结构体,并提供各自的实现。记得在头文件中使用包含保护。
亲手试试
#include <stdio.h>
#include "shape.h"
// TODO: 实现 test_draw 函数
// - 接收一个 const Shape* 参数
// - 打印 "Drawing test shape"
void test_draw(const Shape* shape) {
// TODO: 打印要求的消息
}
// TODO: 实现 test_area 函数
// - 接收一个 const Shape* 参数
// - 返回 42.0
double test_area(const Shape* shape) {
// TODO: 返回测试用的面积值
}
int main() {
// TODO: 创建一个 Shape 实例
// TODO: 将 shape 连接到 test_draw 和 test_area 函数
// TODO: 通过接口调用 draw
// TODO: 通过接口调用 area,并将结果保留一位小数后打印
// 格式:"Area: %.1f\n"
return 0;
}
面向对象编程中的所有课
自己练习: C 在线编译器