Trong C++ từ khóa static được dùng để kiểm soát phạm vi và vòng đời của biến hoặc function.
Nó giúp biến/function tồn tại lâu hơn phạm vi thông thường và có thể được chia sẻ giữa các đối tượng hoặc lần gọi hàm.
Các cách sử dụng static trong C++
- Trong hàm → giữ giá trị giữa các lần gọi.
- Trong lớp/struct/union → Biến/hàm dùng chung cho mọi object (thành viên chung, không gắn với instance)
- Trong namespace/file → Giới hạn phạm vi trong file (internal linkage)
- Trong template → mỗi kiểu template có biến static riêng.
- Phạm vi file → tránh xung đột tên giữa nhiều file.
1. Biến static trong hàm
Khai báo bên trong hàm: biến chỉ được khởi tạo một lần duy nhất và giữ giá trị giữa các lần gọi hàm.
// Gọi nhiều lần sẽ in ra 1 2 3... thay vì reset về 0.
void f() {
static int count = 0;
count++;
cout << count << " ";
}
2. Biến static, hàm static trong lớp
Biến static dùng chung cho tất cả đối tượng của lớp, không phụ thuộc vào từng instance. Ứng dụng: đếm số lượng đối tượng, lưu cấu hình chung, quản lý tài nguyên.
class MyClass {
static int counter;
};
int MyClass::counter = 0;
Hàm static không gắn với đối tượng cụ thể, không có con trỏ this. Chỉ có thể truy cập các thành viên static khác trong lớp. Thường dùng để thao tác dữ liệu chung hoặc tạo factory method
class MyClass {
static int counter;
public:
static void showCounter() {
cout << counter;
}
};
3. Static trong struct hoặc union
- Tương tự như trong class, biến/hàm static trong
structhoặcunioncũng là thành viên chung, không gắn với instance.
3. Biến static ở phạm vi file
Khi khai báo ngoài hàm/lớp, static giới hạn phạm vi biến/hàm chỉ trong file hiện tại (internal linkage). Dùng để tránh xung đột tên giữa nhiều file trong dự án
4. Static trong khối namespace
Khi khai báo biến hoặc hàm static trong namespace (ngoài lớp), nó có internal linkage: chỉ dùng được trong file hiện tại. Đây là cách để tránh xung đột tên khi nhiều file có cùng hàm/biến.
5. Static trong template
Mỗi instantiation của template có biến static riêng biệt.
// Gọi f<int>() và f<double>() sẽ có hai biến counter độc lập.
template<typename T>
void f() {
static int counter = 0;
counter++;
cout << counter << endl;
}
Static với biến toàn cục
- Nếu không có
static, biến toàn cục có external linkage (có thể truy cập từ file khác quaextern). - Nếu có
static, biến toàn cục chỉ tồn tại trong file hiện tại → giúp đóng gói và tránh lộ ra ngoài.
#include <iostream>
using namespace std;
// 1. Static trong hàm
void demoFunction() {
static int counter = 0; // giữ giá trị giữa các lần gọi
counter++;
cout << "demoFunction gọi lần: " << counter << endl;
}
// 2. Static trong lớp
class MyClass {
static int objectCount; // biến dùng chung cho mọi đối tượng
public:
MyClass() { objectCount++; }
~MyClass() { objectCount--; }
static void showCount() { // hàm static
cout << "Số lượng đối tượng hiện tại: " << objectCount << endl;
}
};
int MyClass::objectCount = 0; // định nghĩa biến static
// 3. Static trong template
template<typename T>
void demoTemplate() {
static int templateCounter = 0; // mỗi kiểu T có biến riêng
templateCounter++;
cout << "demoTemplate<" << typeid(T).name() << "> gọi lần: "
<< templateCounter << endl;
}
// 4. Static ở phạm vi file (internal linkage)
static int fileScopeVar = 42; // chỉ dùng trong file này
int main() {
// Static trong hàm
demoFunction();
demoFunction();
// Static trong lớp
MyClass a, b;
MyClass::showCount();
{
MyClass c;
MyClass::showCount();
}
MyClass::showCount();
// Static trong template
demoTemplate<int>();
demoTemplate<int>();
demoTemplate<double>();
// Static ở phạm vi file
cout << "fileScopeVar = " << fileScopeVar << endl;
return 0;
}
demoFunction sẽ in số lần gọi tăng dần (1, 2, …) nhờ biến static giữ giá trị.
MyClass::showCount cho thấy biến static trong lớp được chia sẻ giữa các đối tượng.
demoTemplate<int> và demoTemplate<double> có biến static riêng biệt → bộ đếm độc lập.
fileScopeVar chỉ tồn tại trong file hiện tại, không thể truy cập từ file khác.