標籤:

C++ 關於 static 對象定義問題?

class Example {
public:
constexpr static double rate = 6.5;
constexpr static int vecSize = 20;
static vector& vec(vecSize);
};
const double Example::rate;
vector& Example::vec;

上述代碼中 static vector& vec(vecSize); 本意是聲明一個靜態的 vector& 對象,用 () 來進行初始化。但是在 VS 2015 下,static vector& vec(vecSize); 被認為是函數定義。

目的不變的情況下,怎麼修改才能使編譯通過?


在C++的類定義內,static成員前的static意思是對一個變數的聲明,而非定義。靜態成員變數的初始化通常必須在類的定義外,即.cpp文件里而不是.h里。只有少數幾種例外情況下允許對靜態成員進行類內初始化(in-class initialization),它們是:

1. static const members of integral or enumeration type. 例如你的vecSize。

2. 在C++11之後,標記為constexpr的LiteralType靜態成員也可以進行類內初始化。例如你的rate。

也就是說,你應該這麼寫:

// In .h
class Example {
public:
constexpr static double rate = 6.5;
constexpr static int vecSize = 20;
static vector& vec; // 這裡只是對vec的聲明而非定義。
};

// In .cpp
vector& Example::vec(vecSize); // 定義

另外,在全局/靜態區定義類對象通常是很危險的行為。這是因為對這些變數進行初始化的順序不確定,容易產生bug並且很難追查。在Google C++ Style Guide中,這樣的行為是直接禁止的。良好的姿勢是定義為指針,並使用C++11的std::call_once對其進行初始化。


X:static vector& vec(vecSize);

O:static vector& vec{vecSize};

不過vector&又不是整數類型不能這麼寫吧。


(霧,前面大神說得好棒 (TдT),發現自己廢話了)

static成員不能類內初始化,必須在cpp文件里給出其定義。

也有例外。C++98中,static const的整型成員可類內初始化,編譯時一般會被優化展開(因此其實確切講是constexpr)。

不過,還是有一些有趣的。C++11中,非靜態成員可類內初始化,初始化方式只支持賦值的形式和花括弧的形式。(為啥不支持圓括弧呢,大概是和函數長太像了)。

不過,還有一些小陷阱。比如哪天腦抽寫了

std::vector& array(std::istream_iterator&(cin), std::istream_iterator&());

編譯器硬是覺得函數,還是該考慮分開來寫。記得某本effective啥的談過這個問題,打幾個括弧也能解決。但我忘啦,如果有人記得可以告訴我~~(其實這樣寫,臨時對象本身就挺evil的)


推薦閱讀:

python求解八皇后問題中的回溯究竟體現在哪裡了?
是否所有的循環都能用遞歸代替?
為什麼 PLC 梯形圖要這樣設計?意義在哪?
什麼是安全證書,訪問者到底是怎麼校驗安全證書的,服務端返回安全證書後,客戶端再向誰驗證呢?
關於分散式的問題?

TAG:編程 | C |