在 Heresy 來看,C++ 類別(或結構)的資料成員(data member)的初始化,其實一直很麻煩…因為要初始化他的值,不能像一般變數一樣,在宣告的同時就同時定義,變成要初始化的話,會變成一定要去定義類別的建構子才行…
以前的寫法,基本上就是:
class CTest { public: int m_iValue1; public: CTest() : m_iValue1(128) {} };
這樣寫法一個比較麻煩的地方,就是如果有好幾個建構子的話,那每個建構子都給各自去給初始化的值。
例如:
class CTest { public: int m_iValue1; public: CTest() : m_iValue1(128){} CTest(bool) : m_iValue1(128) {} };
這樣的缺點,就是初始化的值會寫好幾次,在變數多、如果要修改會很麻煩,很有可能會不小心出現不一致的狀況…
而在以往的標準下,比較好的方法,可能會是把這些資料成員的的初始化都包成一個函式,讓建構子去呼叫了。
不過,在 C++11 的時候,C++ 標準終於支援 non-static data member initializer 了!
所以如果只是要初始化資料成員,就可以簡單寫成:
class CTest { public: int m_iValue1 = 128; };
這樣一來,就算有不同的建構子,值的初始化的部分也都只有一個地方,要修改會變得很方便,而且也更好閱讀了~
而如果是靜態資料成員(static data member)呢,在以前的標準下,其實是一個更麻煩的東西…
在類別內部宣告時,並沒有真的去定義他,定義的部分,則是需要另外寫在外面…像下面就是一個例子:
class CTest { public: static int m_iValue1; }; int CTest::m_iValue1 = 128;
而如果 CTest 這個類別是寫在 header 檔的話,那這個靜態資料成員的定義,變成一定得開一個 cpp 檔來編譯,才不會因為多次 include 造成多重定義。
到了 C++17,由於加入了「inline variable」的特性,允許針對變數加上「inline」來確保他只會有一份,所以可以直接寫成:
class CTest { public: inline static int m_iValue1 = 128; };
如此一來,要使用類別的靜態資料成員就比以前方便多了。
另外,同樣是因為「inline variable」,現在全域變數(global variable)也可以透過加上 inline,來在宣告的時候同時定義、初始化了~
inline int iGlobal = 10;
這樣,就不必像以前一樣,還得用 extern 的方法來玩了。
這樣對於要寫 header-only 的函式庫的人還說,真的方便很多啊!
參考: