Con trỏ 'Self'
Thuộc phần Lập trình hướng đối tượng trong hành trình C của Coddy. Bài học 7 trên 61.
Trong các ngôn ngữ hướng đối tượng như Python hoặc Java, khi bạn gọi object.method(), ngôn ngữ sẽ tự động truyền chính đối tượng đó vào phương thức. Trong C, bạn phải tự làm việc này bằng cách truyền con trỏ đến struct làm đối số đầu tiên.
Con trỏ này thường được đặt tên là self (mượn từ Python) hoặc this (từ C++). Nó giúp hàm truy cập dữ liệu của struct để đọc hoặc chỉnh sửa dữ liệu đó:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
Con trỏ self giúp hàm hoạt động như một phương thức. Nó biết cần chỉnh sửa người chơi nào. Nếu không có nó, hàm sẽ không có cách nào truy cập vào thực thể cụ thể của cấu trúc. Khi gọi hàm này, bạn truyền địa chỉ của cấu trúc:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health hiện là 75
Dùng con trỏ thay vì truyền trực tiếp struct là điều cần thiết để chỉnh sửa. Nếu bạn truyền struct theo giá trị, hàm sẽ nhận một bản sao và mọi thay đổi sẽ mất khi hàm trả về. Con trỏ đảm bảo các thay đổi vẫn được giữ lại trong struct ban đầu.
Thử thách
DễHãy tạo một module Timer để theo dõi số giây đã trôi qua. Bạn sẽ luyện tập cách dùng mẫu con trỏ "self" để thay đổi trạng thái bên trong của một struct thông qua các hàm hoạt động như phương thức.
Bạn sẽ tạo ba tệp:
timer.h: Khai báo một structTimercó một thành viên duy nhất làint seconds. Đồng thời khai báo hai hàm:timer_tick(nhận con trỏ đến Timer và cộng thêm số giây được chỉ định) vàtimer_reset(nhận con trỏ đến Timer và đặt seconds về 0). Dùng include guard với ký hiệuTIMER_H.timer.c: Triển khai cả hai hàm. Hàmtimer_ticknhậnTimer *selfvàint amount, sau đó cộng amount vào số giây của timer. Hàmtimer_resetnhậnTimer *selfvà đặt số giây của nó về 0.main.c: Tạo một Timer, thực hiện các thao tác trên đó và hiển thị kết quả.
Bạn sẽ nhận được hai đầu vào số nguyên: số giây ban đầu của timer và số giây cần cộng thêm bằng tick.
Trong tệp main:
- Khởi tạo một
Timervới giá trị số giây ban đầu - Gọi
timer_tickđể cộng thêm số giây đã chỉ định - In ra số giây hiện tại
- Gọi
timer_resetđể đặt lại timer - In ra số giây một lần nữa (phải là 0)
In kết quả theo định dạng sau:
After tick: {seconds}
After reset: {seconds}Ví dụ, với giá trị ban đầu là 30 và cộng thêm 15 giây, đầu ra sẽ là:
After tick: 45
After reset: 0Tự làm thử
#include <stdio.h>
#include "timer.h"
int main() {
int initial_seconds, amount_to_add;
scanf("%d", &initial_seconds);
scanf("%d", &amount_to_add);
// TODO: Tạo một Timer và khởi tạo bằng initial_seconds
// TODO: Gọi timer_tick để cộng thêm amount_to_add giây
// TODO: In số giây hiện tại theo định dạng: "After tick: {seconds}"
// TODO: Gọi timer_reset để đặt lại bộ đếm thời gian
// TODO: In lại số giây theo định dạng: "After reset: {seconds}"
return 0;
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình mô-đun
Tệp tiêu đềInclude guardTệp mã nguồnHàm staticÔn tập: Máy tính mô-đun4Tính đóng gói
Khái niệm con trỏ mờĐịnh nghĩa struct mờHàm truy xuất và hàm gánKiểm tra tính hợp lệ trong hàm gánÔn tập: Hộp bí mật2Đối tượng và phương thức
Struct dưới dạng đối tượngCon trỏ 'Self'Tính đúng đắn của constCon trỏ và giá trịPhương thức hỗ trợÔn tập: trình quản lý Point5Dự án: Tài khoản ngân hàng đơn giản
Thiết lập dự ánTriển khai tài khoản3Vòng đời đối tượng
Mẫu hàm khởi tạoMẫu hàm hủyKhởi tạo trên ngăn xếpSao chép sâuÔn tập: lớp bao bọc chuỗi6Kế thừa bằng cách kết hợp
Nhúng structQuy tắc thành viên đầu tiênTruy cập thành viên lớp chaUpcastingÔn tập: hệ phân cấp hình dạngTự luyện tập: Trình biên dịch C online