vtables

Trong post trước có nói về v-table, v-table là gì!? Với lập trình procedural truyền thống, gọi hàm thực chất là một lệnh hợp ngữ (Assembly), chỉ cần một lệnh JMP – Jump là nhảy ngay đến vùng nhớ chứa đoạn mã – hàm cần thực hiện! Nên gọi hàm trong ngôn ngữ C có tốc độ nhanh, nhanh đến mức không tưởng. Nhưng sự việc không đơn giản như vậy với các ngôn ngữ hướng đối tượng, như C++. Lấy ví dụ như: a->some_function(), trong trường hợp đơn giản nhất, ta cần nhảy 2 lần, lần đầu đến vùng nhớ chứa đối tượng (object) ‘a’, sau đó mới tìm trong vùng nhớ đó con trỏ đến hàm ‘some_function’ và nhảy thêm một lần nữa. Nhưng sự việc không đơn giản như vậy vì OOP có tính kế thừa, có nhiều phiên bản khác nhau của cùng một hàm ảo, những phiên bản này được chứa trong một cái bảng gọi là v-table, và việc gọi hàm lúc này bao gồm: 1. nhảy đến vùng nhớ bắt đầu đối tượng ‘a’, 2. tìm xem trong v-table của ‘a’ địa chỉ của hàm cần gọi, 3. nhảy đến vùng nhớ chính xác của hàm đó. Và cái bảng v-table này càng ngày càng lớn nếu kế thừa nhiều cấp, 20 ~ 30 cấp cũng là việc đã từng thấy! Sự việc bắt đầu trở nên phức tạp hơn nữa với những ngôn ngữ hỗ trợ đa kế thừa, đối tượng ‘a’ có thể kế thừa từ 1, 2 hay nhiều lớp khác nhau!

Lúc đó, compiler sẽ phải tạo ra nhiều v-table, và việc gọi hàm là một công cuộc tìm kiếm, tra bảng dài lê thê, thay vì chỉ một lệnh hợp ngữ JMP đơn giản! Thời gian tiêu tốn cho việc gọi hàm có thể giao động đâu đó trong khoảng 5 ~ 50% toàn bộ thời gian chạy chương trình. Đến tận ngày hôm nay, mấy chục năm sau khi các ngôn ngữ hướng đối tượng ra đời, bản chất của việc gọi hàm vẫn không đổi, và vẫn chưa có cải tiến nào mang tính cách mạng xảy ra! OOP đúng là một mô hình rõ ràng, dễ hiểu đối với lập trình viên, nhưng cực kỳ đau khổ cho những người làm compiler! OOP sinh ra, đầu tiên và trên hết là cho lập trình UI, mỗi cửa sổ, mỗi nút bấm trên UI là một đối tượng – object, nguyên thủy là vậy, về sau người ta mới mở rộng OOP từ UI sang những lĩnh vực khác! Nên những người làm ứng dụng lớn, cần lớp lang, cấu trúc rõ ràng, những người đó sẽ cảm thấy khó hiểu khi những coder ở mức thấp bên dưới chỉ thích procedural! OOP đúng là rõ ràng và tiện lợi, nhưng không phải là cách tiếp cận duy nhất đối với các vấn đề lập trình, mọi việc có thể sẽ thay đổi! Và nhiều coder không hiểu vì sao một số người cố sống cố chết bám vào một số phong cách xưa cũ, vì… bản năng mách bảo rằng làm như thế mới là đúng!