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