“Self”指针
本课属于 Coddy C 学习旅程的“面向对象编程”单元。第 7 课,共 61 课。
在 Python 或 Java 这类面向对象的语言中,调用 object.method() 时,语言会自动将对象本身传递给方法。在 C 中,我们必须手动完成这一步,将指向结构体的指针作为第一个参数传递。
这个指针通常命名为 self(借自 Python)或 this(来自 C++)。它让函数能够访问结构体的数据,以便读取或修改这些数据:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
self 指针使这个函数能够像方法一样工作。它知道要修改哪个玩家。没有它,这个函数就无法访问特定的结构体实例。调用这个函数时,你需要传入结构体的地址:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health 现在是 75
要修改结构体,必须使用指针,而不是直接传递结构体。如果按值传递结构体,函数收到的会是一个副本,函数返回时所做的任何更改都会丢失。指针可以确保更改保留在原始结构体中。
挑战
简单我们来构建一个跟踪已过秒数的 Timer 模块。你将练习使用“self”指针模式,通过充当方法的函数来修改结构体的内部状态。
你将创建三个文件:
timer.h:声明一个只有一个int seconds成员的Timer结构体。还要声明两个函数:timer_tick(接收一个指向 Timer 的指针,并增加指定的秒数)和timer_reset(接收一个指向 Timer 的指针,并将秒数重置为零)。使用符号TIMER_H设置包含保护。timer.c:实现这两个函数。timer_tick函数应接收一个Timer *self和一个int amount,然后将 amount 加到计时器的秒数上。timer_reset函数应接收一个Timer *self,并将它的秒数设为零。main.c:创建一个 Timer,对它执行操作,并显示结果。
你将收到两个整数输入:计时器的初始秒数和通过 tick 要增加的秒数。
在主文件中:
- 使用初始秒数值初始化一个
Timer - 调用
timer_tick来增加指定的秒数 - 打印当前秒数
- 调用
timer_reset来重置计时器 - 再次打印秒数(应为 0)
按照以下格式打印结果:
After tick: {seconds}
After reset: {seconds}例如,初始值为 30,并增加 15 秒时,输出如下:
After tick: 45
After reset: 0亲手试试
#include <stdio.h>
#include "timer.h"
int main() {
int initial_seconds, amount_to_add;
scanf("%d", &initial_seconds);
scanf("%d", &amount_to_add);
// TODO:创建一个 Timer,并用 initial_seconds 初始化它
// TODO:调用 timer_tick,增加 amount_to_add 秒
// TODO:按格式 "After tick: {seconds}" 输出当前秒数
// TODO:调用 timer_reset 重置计时器
// TODO:按格式 "After reset: {seconds}" 再次输出秒数
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C 在线编译器