Cấu trúc dữ liệu trong C/C++

struct trong C và class trong C++

Trong bài học này, bạn sẽ mô hình hóa một tài khoản ngân hàng bằng struct trong C và class trong C++, qua đó thấy được sự khác biệt giữa hai cách tiếp cận.

Giới thiệu

Trong C, struct dùng để nhóm các dữ liệu liên quan lại với nhau, còn các hàm xử lý được viết riêng bên ngoài. Trong C++, class kết hợp dữ liệu và hàm thành viên (member function) trong cùng một kiểu, đồng thời có thể ẩn dữ liệu bằng từ khóa private để bảo vệ tính đúng đắn của đối tượng.

Những điểm quan trọng

  • Xác định những điều kiện luôn phải đúng (invariant) của cấu trúc dữ liệu trước khi viết các thao tác.
  • Xử lý đầy đủ các trường hợp rỗng, đầy và cấp phát bộ nhớ thất bại.
  • Đánh giá cả độ phức tạp lẫn cách quản lý vùng nhớ của từng thao tác.

Code ví dụ bằng C và C++

C
Chạy code →
main.c
#include <stdio.h>

typedef struct {
    const char *owner;
    double balance;
} Account;

void deposit(Account *account, double amount) {
    if (amount > 0) {
        account->balance += amount;
    }
}

int main(void) {
    Account account = {"Ada", 100.0};
    deposit(&account, 25.0);
    printf("%s: %.2f\n", account.owner, account.balance);
    return 0;
}
Kết quả khi chạy
Ada: 125.00
C++
Chạy code →
main.cpp
#include <iomanip>
#include <iostream>
#include <string>
#include <utility>

class Account {
    std::string owner_;
    double balance_;

public:
    Account(std::string owner, double balance)
        : owner_(std::move(owner)), balance_(balance) {}

    void deposit(double amount) {
        if (amount > 0) {
            balance_ += amount;
        }
    }

    void print() const {
        std::cout << owner_ << ": " << std::fixed
                  << std::setprecision(2) << balance_ << '\n';
    }
};

int main() {
    Account account("Ada", 100.0);
    account.deposit(25.0);
    account.print();
}
Kết quả khi chạy
Ada: 125.00

So sánh C và C++

Ở phiên bản C, hàm deposit nhận con trỏ đến struct Account và chỉ cộng tiền khi số tiền dương, nhưng bất kỳ đoạn code nào cũng có thể sửa trực tiếp balance. Ở phiên bản C++, balance_ được khai báo trước từ khóa public: nên mặc định là private, và chỉ thay đổi được qua các phương thức hợp lệ như deposit(), nên rất khó tạo ra trạng thái sai như số dư bị gán tùy ý.

C

Dữ liệu (struct) và các thao tác thường tách rời, bộ nhớ được cấp phát và giải phóng thủ công.

C++

Class và container có thể tự bảo vệ tính đúng đắn của dữ liệu và tự quản lý tài nguyên.

Bài tập mở rộng

Hãy chạy cả hai phiên bản, sau đó thử thay đổi code để quan sát sự khác biệt về mức độ an toàn mà mỗi ngôn ngữ mang lại.

  • Thêm kiểm thử cho trạng thái rỗng và khi đạt giới hạn dung lượng.
  • Viết phần giải phóng bộ nhớ và kiểm tra rò rỉ bộ nhớ.
  • So sánh độ phức tạp với container tương ứng của thư viện chuẩn.

Luyện tập với thử thách

Áp dụng kiến thức của bài học này để giải một bài toán thực tế. Mỗi thử thách chạy ngay trên trình duyệt, có kiểm thử tức thì và AI nhận xét.

Tất cả thử thách