Menu
CoddyTech

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.

challenge icon

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) Temperature có một thành viên double 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)
    Dùng các chỉ thị bảo vệ include với ký hiệu TEMPERATURE_H.
  • temperature.c: Cài đặt cả ba hàm. Hàm temp_display cần in theo định dạng Current: {celsius}C. Hàm temp_to_fahrenheit cần trả về celsius * 9.0 / 5.0 + 32.0. Hãy nhớ rằng các hàm dùng con trỏ const khô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:

  1. Khởi tạo một Temperature với giá trị celsius ban đầu
  2. Gọi temp_display để hiển thị nhiệt độ ban đầu
  3. Gọi temp_adjust để điều chỉnh nhiệt độ theo mức điều chỉnh
  4. Gọi lại temp_display để hiển thị nhiệt độ đã cập nhật
  5. 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}F

Dù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.0F

Tự 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;
}
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch C online