Tính đúng đắn của const
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 8 trên 61.
Khi viết các hàm hoạt động như phương thức, một số hàm nên sửa đổi đối tượng (như player_take_damage), trong khi những hàm khác chỉ nên đọc dữ liệu mà không thay đổi gì. Từ khóa const giúp bạn bắt buộc tuân theo sự phân biệt này ở cấp độ trình biên dịch.
Khi đánh dấu tham số con trỏ là const, bạn cam kết hàm sẽ không sửa đổi dữ liệu mà nó trỏ đến. Nếu vô tình cố thay đổi một thành viên, trình biên dịch sẽ báo lỗi:
typedef struct {
int x;
int y;
} Point;
// Hàm (function) này chỉ có thể ĐỌC điểm
void point_print(const Point *self) {
printf("(%d, %d)\n", self->x, self->y);
// self->x = 10; // LỖI: không thể sửa đổi qua con trỏ const
}
// Hàm này có thể SỬA ĐỔI điểm
void point_move(Point *self, int dx, int dy) {
self->x += dx;
self->y += dy;
}
Tham số const Point *self cho trình biên dịch và những lập trình viên khác biết rằng point_print là một thao tác “getter” hoặc chỉ đọc. Đây gọi là tính đúng đắn của const: dùng const ở mọi nơi không cần sửa đổi.
Bài luyện tập này giúp phát hiện bug sớm. Nếu bạn viết một hàm hiển thị và vô tình sửa đổi một trường, trình biên dịch sẽ dừng bạn ngay lập tức thay vì để bug lọt vào chương trình.
Thử thách
DễHãy tạo một module Temperature để lưu giá trị nhiệt độ và cung cấp các thao tác chỉ đọc và chỉnh sửa. Điều này sẽ giúp bạn luyện tập cách dùng con trỏ const để phân biệt rõ các hàm chỉ đọc dữ liệu với các hàm thay đổi dữ liệu.
Bạn sẽ tạo ba tệp:
temperature.h: Khai báo một cấu trúc (struct)Temperaturecó một thành viêndouble celsius. Đồng thời khai báo ba hàm:temp_display: nhận một con trỏconstđến Temperature và in nhiệt độ hiện tại (chỉ đọc)temp_adjust: nhận một con trỏ thông thường đến Temperature và một giá trị double, sau đó cộng giá trị đó vào celsius (chỉnh sửa)temp_to_fahrenheit: nhận một con trỏconstđến Temperature và trả về giá trị đã chuyển đổi sang Fahrenheit (chỉ đọc)
TEMPERATURE_H.temperature.c: Cài đặt cả ba hàm. Hàmtemp_displaycần in theo định dạngCurrent: {celsius}C. Hàmtemp_to_fahrenheitcần trả vềcelsius * 9.0 / 5.0 + 32.0. Hãy nhớ rằng các hàm dùng con trỏconstkhông thể chỉnh sửa dữ liệu của cấu trúc.main.c: Tạo một Temperature, thực hiện các thao tác và hiển thị kết quả.
Bạn sẽ nhận hai đầu vào: giá trị celsius ban đầu (dạng double) và mức điều chỉnh (dạng double).
Trong tệp main:
- Khởi tạo một
Temperaturevới giá trị celsius ban đầu - Gọi
temp_displayđể hiển thị nhiệt độ ban đầu - Gọi
temp_adjustđể điều chỉnh nhiệt độ theo mức điều chỉnh - Gọi lại
temp_displayđể hiển thị nhiệt độ đã cập nhật - In giá trị chuyển đổi sang Fahrenheit bằng
temp_to_fahrenheit
In kết quả theo định dạng này:
Current: {celsius}C
Current: {celsius}C
Fahrenheit: {fahrenheit}FDùng %.1f cho tất cả giá trị nhiệt độ để hiển thị một chữ số thập phân.
Ví dụ, với giá trị ban đầu là 20.0 và mức điều chỉnh là 5.0, đầu ra sẽ là:
Current: 20.0C
Current: 25.0C
Fahrenheit: 77.0FTự làm thử
#include <stdio.h>
#include "temperature.h"
int main() {
double initial_celsius, adjustment;
scanf("%lf", &initial_celsius);
scanf("%lf", &adjustment);
// TODO: Tạo một cấu trúc Temperature và khởi tạo bằng initial_celsius
// TODO: Gọi temp_display để hiển thị nhiệt độ ban đầu
// TODO: Gọi temp_adjust để điều chỉnh nhiệt độ theo giá trị adjustment
// TODO: Gọi lại temp_display để hiển thị nhiệt độ sau khi điều chỉnh
// TODO: In ra nhiệt độ chuyển đổi sang Fahrenheit bằng temp_to_fahrenheit
// Định dạng: "Fahrenheit: %.1fF\n"
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