在C ++中初始化私有靜態數據成員的最佳方法是什麼? 我在頭文件中嘗試了此操做,但它給了我奇怪的連接器錯誤: 函數
class foo { private: static int i; }; int foo::i = 0;
我猜這是由於我沒法從類外部初始化私有成員。 那麼最好的方法是什麼? spa
對於之後這個問題的觀衆,我想指出,您應該避免monkey0506的建議 。 code
頭文件用於聲明。 get
頭文件將針對每一個直接或間接#includes
.cpp
文件進行一次.cpp
,而且任何函數以外的代碼都將在程序初始化時運行在main()
以前。 編譯器
經過輸入: foo::i = VALUE;
在頭文件中, foo:i
將爲每一個.cpp
文件分配值VALUE
(不管是什麼),而且這些分配將在運行main()
以前以不肯定的順序(由連接器肯定main()
進行。 it
若是咱們在其中一個.cpp
文件中#define VALUE
爲其餘數字怎麼辦? 它將編譯良好,而且在運行程序以前,咱們將沒法知道哪個獲勝。 io
絕對不要將執行的代碼放入標頭中,緣由與您從未#include
.cpp
文件相同。 編譯
包含衛士(我贊成您應該始終使用)來保護您免受不一樣的傷害:同一頭文件在編譯單個.cpp
文件時屢次間接#include
d class
若是使用標題防禦,也能夠將分配包括在標題文件中。 我將這種技術用於我建立的C ++庫。 得到相同結果的另外一種方法是使用靜態方法。 例如... 變量
class Foo { public: int GetMyStatic() const { return *MyStatic(); } private: static int* MyStatic() { static int mStatic = 0; return &mStatic; } }
上面的代碼具備不須要CPP /源文件的「好處」。 一樣,這是我用於C ++庫的一種方法。
類聲明應該在頭文件中(若是未共享,則在源文件中)。
檔案:foo.h
class foo { private: static int i; };
可是初始化應該在源文件中。
檔案:foo.cpp
int foo::i = 0;
若是初始化在頭文件中,則每一個包含頭文件的文件都將具備靜態成員的定義。 所以,在連接階段,您將獲得連接器錯誤,由於初始化變量的代碼將在多個源文件中定義。 static int i
的初始化必須在任何函數以外完成。
注意: Matt Curtis:指出,若是靜態成員變量爲const int類型(例如int
, bool
, char
),則C ++容許簡化上述操做。 而後,您能夠直接在頭文件的類聲明中聲明和初始化成員變量:
class foo { private: static int const i = 42; };
對於變量 :
foo.h:
class foo { private: static int i; };
foo.cpp:
int foo::i = 0;
這是由於程序中只能有一個foo::i
實例。 它有點像頭文件中的extern int i
和源文件中的int i
。
對於常量 ,能夠將值直接放在類聲明中:
class foo { private: static int i; const static int a = 42; };
int foo::i = 0;
是用於初始化變量的正確語法,可是它必須位於源文件(.cpp)中,而不是標頭中。
由於它是一個靜態變量,因此編譯器僅須要建立一個副本。 您必須在代碼中的某些位置插入「 int foo:i」行,以告訴編譯器將其放置在何處,不然會出現連接錯誤。 若是在標頭中,則將在每一個包含標頭的文件中得到一個副本,所以請從連接器獲取多個已定義的符號錯誤。