C++ 如何初始化靜態(tài)類成員
C++ 如何初始化靜態(tài)類成員
我們定義如下類:
//A.h
class?A
{
private:
????static?const?int?m?=?5;
????static?int?n;
????static?vector<int>?buf;
};
其中包含三個私有的靜態(tài)類成員,C++規(guī)定const靜態(tài)類成員可以直接初始化,其他非const的靜態(tài)類成員需要在類聲明以外初始化,我們一般選擇在類的實現(xiàn)文件中初始化,初始化的方式是書寫一遍類型的定義:
//A.cpp
int?A::n; ? ? ? ? ? ? ? ??//不指定任何初始值,系統(tǒng)自動初始化為0
vector<int>?A::buf; ? ? ??//調(diào)用vector的默認構(gòu)造函數(shù)來初始化
?? ? ? ? ? ? ? ? ? ? ? ? ? ?//注意:調(diào)用默認構(gòu)造函數(shù)時,不要使用括號,否則編譯器將把A::buf()當(dāng)做靜態(tài)成員函數(shù),
?? ? ? ? ? ? ? ? ? ? ? ? ? ?//但是A::buf()實際沒有被聲明,所以編譯器將報錯
?或者:
//A.cpp
int?A::n(9);??????????????//使用字面量9來初始化n
vector<int>?A::buf(100);??//調(diào)用vector的帶參構(gòu)造函數(shù)來初始化
對于更復(fù)雜的情形 ,如沒有構(gòu)造函數(shù)可以調(diào)用(比如單例模式實現(xiàn)的類),或者需要多步驟才能完成的初始化怎么辦?
假設(shè)有一個類S實現(xiàn)了單例模式,S的實例是通過調(diào)用S的靜態(tài)方法S::GetInstance()來獲得的,現(xiàn)在定義一個包含S作為靜態(tài)成員的類:
//B.h
class?B
{
private:
? ??static?S?s;
};
?按照前面的介紹,我們或許應(yīng)該以下面這種方式初始化s:
//B.cpp
#include?<B.h>
S?B::s;??//編譯器會報錯,因為S沒有可以調(diào)用的構(gòu)造函數(shù)
?解決方法是定義一個靜態(tài)方法,負責(zé)初始化靜態(tài)成員s:
//B.h
class?B
{
public:
????static?S?Init();
private:
????static?S?s;
};
//B.cpp
#include?<B.h>
S?B::Init()
{
????....
????return?S::Instance();
}
S?B::s?=?B::Init();????????????//調(diào)用靜態(tài)函數(shù)初始化靜態(tài)成員
上例中,為了初始化類B的靜態(tài) 成員s,我們定義了一個公有的靜態(tài)方法Init(),它可以很好的工作。但是,在現(xiàn)實的工程中,我們很可能碰到更進一步的要求,就是希望Init()僅僅作為靜態(tài)變量s的初始化器使用,而不能使用在程序中別的地方,但是我們又不能把Init()聲明為private,這樣Init()就不能被調(diào)用來初始化s了。解決的方法是使用內(nèi)部類:
//B.h
class?B
{
private:
????class?C
????{
????public:
????????static?S?InitB();
????};
????static?S?s;
};
//B.cpp
S?B::C::InitB()
{
????....
????return?S::Instance();
}
S?B::s?=?B::C::InitB();?????????//調(diào)用內(nèi)部類的靜態(tài)成員函數(shù)來初始化靜態(tài)數(shù)據(jù)成員
因為C是B的內(nèi)部類,C僅在B的作用域范圍內(nèi)可見,如果程序的其他地方調(diào)用了B::C::InitB(),編譯器將報錯,因為C不可訪問。?
?
最后說一下,從初始化的方式可以看出來,類的靜態(tài)數(shù)據(jù)成員其實就是“帶類名”的全局變量。
靜態(tài)數(shù)據(jù)成員必須顯式初始化,否則在類方法中操作該成員時,將報鏈接錯誤?undefined reference to `A::buf'?(gcc中)
分類:?C/C++
C++ 如何初始化靜態(tài)類成員 - fre2technic - 博客園 (cnblogs.com)