结构体嵌入
本课属于 Coddy C 学习旅程的“面向对象编程”单元。第 28 课,共 61 课。
在 C++ 或 Java 这类面向对象的语言中,继承允许一个类从父类获取属性。C 没有内置的继承功能,但我们可以用一种叫作组合的技术来模拟继承:把一个结构体放进另一个结构体中。
这个想法很简单:如果 Child 需要 Parent 的所有属性,我们就将 Parent 结构体嵌入为 Child 的成员。
typedef struct {
int id;
char name[50];
} Parent;
typedef struct {
Parent parent; // 嵌入的结构体
int grade;
} Child;这里,Child 包含 Parent 拥有的所有内容,还包含它自己的 grade 字段。这就是组合:子类“拥有”一个父类,而不是“是”一个父类,但效果与继承类似。
要通过子实例访问父级成员,你需要使用两次点运算符:
Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;这种模式构成了在 C 中构建类型层次结构的基础。通过将基结构体嵌入为第一个成员,我们可以使用强大的技术,并将在接下来的课程中探索这些技术。
挑战
简单让我们来构建一个简单的员工管理系统,演示结构体嵌入:这是 C 中继承的基础。
你将创建一个层级结构,其中 Employee 包含一个 Person。这反映了继承的工作方式:员工“是一个”人,并且有额外的工作相关信息。将 Person 结构体嵌入 Employee 结构体后,你就能获得这个人的所有属性,以及员工特有的字段。
你将把代码组织在三个文件中:
types.h:在这里定义两个结构体,并添加包含保护。首先,创建一个Person结构体,包含两个字段:name(一个长度为 50 的字符数组)和age(一个整数)。然后定义一个Employee结构体,将Person作为第一个成员嵌入其中,并添加一个employee_id字段(一个整数)。types.c:实现一个名为print_employee的函数,它接收一个指向Employee的指针,并打印员工信息。使用你学过的点号和箭头链式语法访问嵌入的人物数据。main.c:创建一个Employee变量,为它的所有字段赋值(包括嵌入的人物姓名和年龄),然后使用你的打印函数显示信息。
你将收到三个输入:员工的姓名(一个字符串)、年龄(一个整数)和员工 ID(一个整数)。
你的 print_employee 函数应按以下格式输出员工信息:
Employee: Alice
Age: 28
ID: 1001其中,Alice 是姓名,28 是年龄,1001 是输入中的员工 ID。
记得通过父成员访问嵌入结构体的成员。例如,要访问姓名,你需要先通过 person 成员进行访问。
亲手试试
#include <stdio.h>
#include <string.h>
#include "types.h"
int main() {
// 读取输入
char name[50];
int age;
int employee_id;
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = '\0'; // 移除换行符
scanf("%d", &age);
scanf("%d", &employee_id);
// TODO:创建一个 Employee 变量
// TODO:填写嵌入的 person 的姓名和年龄
// 提示:用 strcpy 复制姓名,通过 employee.person.name 访问
// TODO:设置 employee_id
// TODO:传入指向你的 employee 的指针,调用 print_employee
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C 在线编译器