ภาพรวม
Static Class Members ใน C++ มีกฎการ Initialize ที่เฉพาะเจาะจง:
- Static Data Members: ต้องมี Definition (นิยาม) ใน Global/namespace Scope พอดี 1 ครั้ง
- Initialization เกิดขึ้น ก่อน main() เริ่มต้น (Static Initialization Phase)
- ถ้าไม่ระบุ Initializer จะถูก Zero-initialize อัตโนมัติ
- Constant Static Members (
static const integralหรือconstexpr) สามารถ Initialize ในคลาสได้ (C++11) inline static(C++17) สามารถ Define และ Initialize ในคลาสได้เลย
ลำดับการ Initialize
- Zero Initialization: ทุก Static/Thread-local Variables = 0/Nullptr
- Constant Initialization: constexpr/const variables ที่มี Constant Expression
- Dynamic Initialization: Static variables ที่มี Initializer ที่ไม่ใช่ Constant Expression (เรียก Constructor, Function, etc.)
- ลำดับใน Translation Unit เดียวกัน: ตามลำดับที่ปรากฏในโค้ด
- ลำดับข้าม Translation Units: Unspecified (Initialization Order Fiasco)
ตัวอย่างโค้ด
#include <iostream>
using namespace std;
class Example {
public:
static int a; // Declaration
static const int MAX = 100; // C++11: In-class init OK (const integral)
static constexpr double PI = 3.14159; // C++11: constexpr
void func() {
cout << "The value of static member a: " << a;
}
};
// Definition (จำเป็นสำหรับ Non-const Static Members)
int Example::a = 20; // Definition + Initialization
int main() {
Example obj;
obj.func();
return 0;
}
ผลลัพธ์
The value of static member a: 20
C++17 Inline Static Members (แนะนำ)
class Modern {
public:
inline static int count = 0; // Define + Initialize ในคลาสได้เลย
inline static const int MAX = 100; // const ก็ได้
inline static vector<int> cache; // Non-integral types ก็ได้
Modern() { count++; }
~Modern() { count--; }
};
Initialization Order Fiasco (ปัญหาลำดับ Init)
// File1.cpp
#include "File2.hpp"
static int x = getY() + 1; // ใช้ y จาก File2 - อาจยังไม่ Init!
// File2.cpp
static int y = 10;
int getY() { return y; }
แก้ไข: ใช้ Function-Local Static (Meyers' Singleton)
int& getX() {
static int x = getY() + 1; // Init ครั้งแรกที่เรียก - Safe!
return x;
}
สรุปการ Initialize
| ประเภท | In-Class Init | Out-of-Class Definition | หมายเหตุ |
|---|---|---|---|
| static int (Non-const) | ❌ ไม่ได้ (Pre-C++17) | ✅ จำเป็น | C++17: inline static OK |
| static const int | ✅ ได้ (C++11) | ❌ ไม่ต้อง (ถ้า ODR-used ต้อง Define) | Integral Type เท่านั้น |
| static constexpr | ✅ ได้ (C++11) | ❌ ไม่ต้อง | Implicitly Inline |
| static non-integral | ❌ ไม่ได้ (Pre-C++17) | ✅ จำเป็น | C++17: inline static OK |