Static keyword

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 struct hoặc union cũ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 qua extern).
  • 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.

Leave a Comment