當開發header only library時,有時候會需要static or global物件,但因為C++ ODR的原因,
當物件被重複定義時在link階段會報錯。
例如
//X.h class X { public: static int m; //這只是declaration }; //main.cpp #include "X.h" int main() { X a; a.m = 0; return 0; }
/tmp/ccaFpbvF.o: In function `main':
t.cc:(.text+0x6): undefined reference to `X::m'
collect2: error: ld returned 1 exit status
因為沒有定義
所以需要加上out of class definition, int X::m; (static int default to 0)
但是理論上這是需要library開發者處理的, 使用者只需要include file
但不應該寫在.h檔 因為有可能會出現在多個translation unit內 這樣會違反ODR – one definition rule
最簡單的方式是提供一個cpp 把所有需要定義的變數寫在裡面。
請使用者在編譯時加進去
然而如果是template,這樣子做就行不通了,因為有可能會有使用者自定義的型別,這在一開始是無法知道的。
事實上,碰到static or global需要定義的變數時,可以用
singleton的方式來處理,利用把定義藏在function內,而function本身又是可以被inline來達成
//test.h templateclass X { X() { x = T(); } public: inline static X& get(); T x; }; template inline X & X ::get() { static X m; return m; } //test.cc #include "test.h" #include int main () { typedef X XInt; XInt& x = XInt::get(); std::cout << x.x << std::endl; return 0; }
參考: http://en.cppreference.com/w/cpp/language/definition