Menu
CoddyTech

访问父类成员

本课属于 Coddy C 学习旅程的“面向对象编程”单元。第 30 课,共 61 课。

现在我们已经了解了结构体嵌入和首个成员规则,接下来重点看看实际应用:如何在函数中读取和修改嵌入的父级数据。

函数接收 Child 结构体(或指向它的指针)时,访问父级的成员需要通过嵌入的结构体进行访问。语法取决于你使用的是值还是指针。

typedef struct {
    int id;
    int score;
} Parent;

typedef struct {
    Parent parent;
    char grade;
} Child;

有了指向 Child 的指针,先使用箭头运算符访问父级,再使用点运算符访问其成员:

void update_score(Child* c, int new_score) {
    c->parent.score = new_score;  // 先用箭头运算符,再用点运算符
}

void print_info(Child* c) {
    printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}

对于值(通过复制传递),全程使用点号:

void show_id(Child c) {
    printf("ID: %d\n", c.parent.id);  // 先用点号,再用点号
}

这种链式访问模式,child->parent.member 或 child.parent.member,是在 C 的组合模型中访问继承数据的方式。它比真正的继承稍微冗长一些,但能明确清楚地表达类型之间的关系。

challenge icon

挑战

简单

让我们构建一个学生评分系统,演示如何访问和修改嵌入式结构体中的数据。你将创建一个层级结构,其中 Student 包含一个嵌入式的 Person,然后编写一些函数,通过子结构体处理父结构体的数据。

你需要将代码分成三个文件:

  • student.h:定义带有包含保护的结构体层级。创建一个 Person 结构体,其中包含 name(一个长度为 50 个字符的字符数组)和 age(一个整数)。然后定义一个 Student 结构体,将 Person 作为第一个成员嵌入其中,并添加一个 grade 字段(一个表示分数的整数)。声明两个函数:set_person_age 接收一个 Student* 和一个新的年龄值;print_student 接收一个 Student* 并显示所有信息。
  • student.c:实现这两个函数。你的 set_person_age 函数应修改嵌入式 Person 结构体中的年龄。在这里,你将练习箭头运算符后接点运算符的语法(s->person.age)。你的 print_student 函数应访问并显示嵌入式 Person 和 Student 自身的所有字段。
  • main.c:创建一个 Student 变量并初始化它的所有字段。然后使用 set_person_age 更新嵌入式 Person 的年龄,并调用 print_student 显示结果。

你将收到四个输入:学生的姓名(一个字符串)、初始年龄(一个整数)、成绩(一个整数),以及新年龄(一个要通过你的函数更新的整数)。

在主文件中,使用初始值创建学生,然后调用 set_person_age 将年龄改为新值,最后调用 print_student 显示更新后的信息。

你的输出应如下所示:

Name: Emma
Age: 21
Grade: 85

其中,Emma 是姓名,21 是更新后的年龄(不是初始年龄),85 是成绩。这里的重点是学习如何通过嵌入式结构体访问父结构体的成员,以读取和写入数据。

亲手试试

#include <stdio.h>
#include <string.h>
#include "student.h"

int main() {
    char name[50];
    int initial_age, grade, new_age;
    
    // 读取输入
    fgets(name, 50, stdin);
    name[strcspn(name, "\n")] = '\0';  // 移除换行符
    scanf("%d", &initial_age);
    scanf("%d", &grade);
    scanf("%d", &new_age);
    
    // TODO: 创建一个 Student 变量
    
    // TODO: 初始化 student 的所有字段
    // 用 strcpy 将 name 复制到内嵌的 person 的 name 字段
    // 将内嵌的 person 的 age 字段设置为 initial_age
    // 设置 student 的 grade 字段
    
    // TODO: 调用 set_person_age,将 age 更新为 new_age
    
    // TODO: 调用 print_student 显示结果
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C 在线编译器