static ở phạm vi file (Internal Linkage)
Vấn đề
Phần tiêu đề “Vấn đề”Bài “Phạm vi biến (Scope)” đã giới thiệu static bên trong một hàm (giữ giá trị giữa các lần gọi). Nhưng static khi dùng ở phạm vi toàn cục của một file (bên ngoài mọi hàm) lại mang ý nghĩa hoàn toàn khác - đây là điểm dễ gây nhầm lẫn cho người mới.
static int counter = 0; // static ở đây nghĩa là: BIẾN NÀY CHỈ NHÌN THẤY ĐƯỢC TRONG file1.cpp
void increase() { counter++;}extern int counter; // Khai báo "tôi biết có biến counter ở đâu đó"
void print_counter() { // std::cout << counter; // LỖI LINK! Không tìm thấy counter, vì nó là static trong file1.cpp}Ý nghĩa thực sự: internal linkage
Phần tiêu đề “Ý nghĩa thực sự: internal linkage”static ở phạm vi file giới hạn liên kết (linkage) của biến/hàm chỉ trong phạm vi file đó - các file .cpp khác trong cùng project không thể truy cập đến nó, dù có dùng extern. Đây là cách “đóng gói” (encapsulation) ở cấp độ file, trước khi C++ có namespace và class.
static int internal_helper_count = 0; // Chỉ dùng nội bộ trong file này
int public_function() { // Không có static - có thể dùng từ file khác internal_helper_count++; return internal_helper_count;}So sánh với biến toàn cục thông thường (không static)
Phần tiêu đề “So sánh với biến toàn cục thông thường (không static)”int global_counter = 0; // KHÔNG static - external linkage, file khác CÓ THỂ dùngextern int global_counter; // OK - tìm thấy global_counter từ file1.cpp lúc link
void increase_from_file2() { global_counter++; // Hoạt động bình thường}Cách hiện đại: dùng namespace ẩn danh (anonymous namespace)
Phần tiêu đề “Cách hiện đại: dùng namespace ẩn danh (anonymous namespace)”C++ hiện đại thường ưu tiên namespace ẩn danh thay vì static ở phạm vi file, vì nó cũng giới hạn phạm vi trong file nhưng linh hoạt hơn (áp dụng được cho cả class, không chỉ biến/hàm đơn lẻ):
namespace { int internal_helper_count = 0; // Chỉ nhìn thấy được trong file này, giống static}
int public_function() { internal_helper_count++; return internal_helper_count;}Tóm tắt
Phần tiêu đề “Tóm tắt”
staticbên trong hàm: giữ giá trị giữa các lần gọi hàm.staticở phạm vi file (biến/hàm toàn cục): giới hạn chỉ nhìn thấy được trong file đó (internal linkage) - hai ý nghĩa hoàn toàn khác nhau của cùng một từ khóa!
staticở phạm vi file là cách “đóng gói” cũ, trước khi có class/namespace- C++ hiện đại thường ưu tiên namespace ẩn danh cho mục đích tương tự