C++ hiện đại và cách làm tương ứng trong C

Đa hình trong C++ và bảng con trỏ hàm trong C

Trong bài học này, bạn sẽ gọi cùng một thao tác cho nhiều loại đối tượng khác nhau bằng hàm ảo trong C++ và con trỏ hàm trong C.

Giới thiệu

Đa hình động (dynamic polymorphism) cho phép phần code sử dụng gọi một thao tác chung, ví dụ tính diện tích, còn mỗi loại đối tượng cụ thể tự quyết định cách thực hiện. C++ hỗ trợ trực tiếp bằng hàm ảo (virtual function), còn trong C có thể mô phỏng bằng con trỏ hàm.

Những điểm quan trọng

  • Hiểu cách làm trong C trước khi học các công cụ trừu tượng của C++.
  • Dùng RAII và ngữ nghĩa giá trị (value semantics) để thể hiện quyền sở hữu tài nguyên.
  • Ưu tiên các công cụ an toàn kiểu của C++ thay vì macro và ép kiểu.

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

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

typedef struct Shape Shape;
struct Shape {
    double value;
    double (*area)(const Shape *shape);
};

double square_area(const Shape *shape) {
    return shape->value * shape->value;
}

int main(void) {
    Shape square = {4.0, square_area};
    printf("area=%.1f\n", square.area(&square));
}
Kết quả khi chạy
area=16.0
C++
Chạy code →
main.cpp
#include <iostream>

struct Shape {
    virtual double area() const = 0;
    virtual ~Shape() = default;
};

struct Square : Shape {
    double side;

    explicit Square(double value) : side(value) {}
    double area() const override { return side * side; }
};

int main() {
    Square square(4);
    const Shape& shape = square;
    std::cout << "area=" << shape.area() << '\n';
}
Kết quả khi chạy
area=16

So sánh C và C++

Trong C, struct Shape lưu một con trỏ hàm area, và mỗi hình gắn hàm tính diện tích riêng, ví dụ square_area. Trong C++, hàm ảo tạo ra cơ chế chọn hàm tương tự một cách tự động. Lớp cơ sở cũng nên có hàm hủy ảo (virtual destructor) để việc xóa đối tượng qua con trỏ lớp cơ sở diễn ra an toàn.

C

C dùng quy ước đặt tên, callback, macro và struct chứa ngữ cảnh.

C++

C++ có sẵn các công cụ trừu tượng có phạm vi rõ ràng, an toàn kiểu và thường không tốn thêm chi phí khi chạy.

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.

  • Tự viết cơ chế bằng C trước, rồi mới dùng tính năng tương ứng của C++.
  • Thay việc giải phóng tài nguyên thủ công bằng RAII.
  • Kiểm tra xem tính năng có phát sinh cấp phát bộ nhớ hoặc lời gọi hàm ảo hay không.

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