當開發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