Bỏ qua để đến nội dung

static ở phạm vi file (Internal Linkage)

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.

file1.cpp
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++;
}
file2.cpp
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
}

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.

utils.cpp
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)”
file1.cpp
int global_counter = 0; // KHÔNG static - external linkage, file khác CÓ THỂ dùng
file2.cpp
extern 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ẻ):

utils.cpp
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;
}

static bê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ự