使用 = default 生成默認(rèn)構(gòu)造函數(shù)
在新標(biāo)準(zhǔn)下草戈,如果我們想要一個(gè)默認(rèn)構(gòu)造函數(shù),我們可以在參數(shù)列表的后面添加= default
來要求編譯器為我們自動(dòng)生成一個(gè)默認(rèn)構(gòu)造函數(shù)椒丧。= default
可以和類內(nèi)部的聲明或者類外部的定義一起出現(xiàn)慢蜓。與任何其他函數(shù)一樣亿絮,如果= default
出現(xiàn)在類體內(nèi),則默認(rèn)構(gòu)造函數(shù)將被內(nèi)聯(lián)岭粤;如果它出現(xiàn)在類外的定義中惜索,則默認(rèn)情況下不會(huì)內(nèi)聯(lián)。
Code:
class Sales_data{
Sales_data() = default; // the default constructor and is inlined
Sales_data(const std::string &s): bookNo(s) { }
private:
std::string bookNo;
};
如果= default
能工作剃浇,那么就要求類的成員變量必須具有默認(rèn)的初始化器(如:內(nèi)置類型int
巾兆,double
,string
等虎囚、其他具有默認(rèn)構(gòu)造函數(shù)的類角塑。)。如果某個(gè)類的成員變量不支持默認(rèn)初始化器對(duì)其進(jìn)行默認(rèn)初始化淘讥,那么必須顯示編寫構(gòu)造函數(shù)來完成各個(gè)成員變量的初始化圃伶。
類類型(Class Type)成員的類內(nèi)初始化器
下面我們以一個(gè)例子來說明。我們除了定義Screen
類,還將定義一個(gè)窗口管理器類Window_mgr
窒朋,它表示給定顯示器上的Screen
集合搀罢。這個(gè)類將有一個(gè)Screen
向量,其中每個(gè)元素代表一個(gè)特定的Screen
對(duì)象侥猩。默認(rèn)情況下榔至,我們希望我們的Window_mgr
類有一個(gè)默認(rèn)構(gòu)造函數(shù)來實(shí)現(xiàn)對(duì)Screen
向量進(jìn)行初始化。 在新標(biāo)準(zhǔn)下欺劳,最佳的實(shí)現(xiàn)方式是使用類內(nèi)初始化器:
Code:
class Window_mgr {
private:
// Screens this Window_mgr is tracking
// by default, a Window_mgr has one standard sized blank Screen
std::vector<Screen> screens{Screen(24, 80, ' ') };
};
當(dāng)我們初始化類類型的成員時(shí)唧取,我們?cè)跒樵摮蓡T類型的構(gòu)造函數(shù)提供參數(shù)。在這種情況下划提,我們使用具有單個(gè)元素的初始化器列表來初始化vector
成員枫弟。該初始化器列表包含一個(gè)Screen
值,該值傳遞給vector <Screen>
構(gòu)造函數(shù)以創(chuàng)建單元素向量鹏往。該值由Screen
構(gòu)造函數(shù)創(chuàng)建媒区,該構(gòu)造函數(shù)采用兩個(gè)大小參數(shù)和一個(gè)字符來創(chuàng)建給定大小的空白屏幕。
正如我們所看到的掸犬,類內(nèi)初始化器必須使用初始化的形式(我們?cè)诔跏蓟?code>Screen的數(shù)據(jù)成員時(shí)使用的方式)或使用花括號(hào)的初始化器列表形式(就像我們對(duì)screens
所做的那樣)。
委托構(gòu)造函數(shù)
新標(biāo)準(zhǔn)擴(kuò)展了構(gòu)造函數(shù)初始值設(shè)定項(xiàng)的使用绪爸,以便讓我們定義所謂的委托構(gòu)造函數(shù)湾碎。委托構(gòu)造函數(shù)使用其自己的類中的另一個(gè)構(gòu)造函數(shù)來執(zhí)行其初始化。它將一些(或全部)工作“委托”給另一個(gè)構(gòu)造函數(shù)奠货。
與任何其他構(gòu)造函數(shù)一樣介褥,委托構(gòu)造函數(shù)具有成員初始化列表和函數(shù)體。在委托構(gòu)造函數(shù)中递惋,成員初始化列表具有單個(gè)條目柔滔,該條目是類本身的名稱。與其他成員初始值設(shè)定項(xiàng)一樣萍虽,該類的名稱后跟帶括號(hào)的參數(shù)列表睛廊。參數(shù)列表必須與類中的另一個(gè)構(gòu)造函數(shù)匹配。
Code:
class Sales_data {
public:
// nondelegating constructor initializes members from corresponding arguments
Sales_data(std::string s, unsigned cnt, double price):
bookNo(s), units_sold(cnt), revenue(cnt*price) { }
// remaining constructors all delegate to another constructor
Sales_data(): Sales_data("", 0, 0) {}
Sales_data(std::string s): Sales_data(s, 0,0) {}
Sales_data(std::istream &is): Sales_data(){ read(is, *this); }
private:
std::string bookNo;
unsigned units_sold;
double revenue;
};
在Sales_data
中杉编,除了一個(gè)構(gòu)造函數(shù)之外的所有構(gòu)造函數(shù)都委托他們的工作超全。第一個(gè)構(gòu)造函數(shù)接受三個(gè)參數(shù),使用這些參數(shù)初始化數(shù)據(jù)成員邓馒,并且沒有進(jìn)一步的工作嘶朱。我們還定義了一個(gè)默認(rèn)構(gòu)造函數(shù),該函數(shù)委托三參數(shù)的構(gòu)造函數(shù)來實(shí)現(xiàn)自己的初始化光酣,而且該構(gòu)造函數(shù)也沒有做其他的工作疏遏。接受字符串的構(gòu)造函數(shù)也將自己的初始化工作委托給三參數(shù)版本。
接受參數(shù)std::istream
的構(gòu)造函數(shù)也是委托構(gòu)造函數(shù)。它將自己的初始化工作委托給默認(rèn)構(gòu)造函數(shù)财异,后者又委托給三參數(shù)構(gòu)造函數(shù)倘零。一旦這些構(gòu)造函數(shù)完成它們的工作,就會(huì)運(yùn)行istream
和構(gòu)造函數(shù)的主體代碼宝当。它的構(gòu)造函數(shù)體調(diào)用read
函數(shù)來讀取給定的istream
视事。
當(dāng)一個(gè)構(gòu)造函數(shù)將初始化工作委托給另一個(gè)構(gòu)造函數(shù)時(shí),被委托的構(gòu)造函數(shù)的初始化器列表和函數(shù)體都會(huì)運(yùn)行庆揩。在Sales_data
中俐东,被委托的構(gòu)造函數(shù)的函數(shù)體剛好為空。如果委托構(gòu)造函數(shù)的函數(shù)體中有代碼订晌,則該代碼在被委托的構(gòu)造函數(shù)返回之后才會(huì)運(yùn)行虏辫。
constexpr構(gòu)造函數(shù)
雖然構(gòu)造函數(shù)不能是const
,但是文字類(literal class)中的構(gòu)造函數(shù)可以是constexpr
函數(shù)锈拨。實(shí)際上砌庄,文字類必須提供至少一個(gè)constexpr
構(gòu)造函數(shù)。
constexpr
構(gòu)造函數(shù)可以以= default
的形式進(jìn)行聲明奕枢。然而constexpr
構(gòu)造函數(shù)需要同時(shí)滿足構(gòu)造函數(shù)的條件(它可以沒有return
語(yǔ)句)和constexpr
函數(shù)的條件(它可以擁有的唯一可執(zhí)行語(yǔ)句是return
語(yǔ)句)娄昆。所以constexpr
構(gòu)造函數(shù)的函數(shù)體通常是空的。我們通過在函數(shù)聲明前加上關(guān)鍵字constexpr
來定義一個(gè)constexpr
構(gòu)造函數(shù)缝彬。
Code:
class Debug {
public:
constexpr Debug(bool b = true): hw(b), io(b), other(b) { }
constexpr Debug(bool h, bool i, bool o):
hw(h), io(i), other(o) { }
constexpr bool any() { return hw || io || other; }
void set_io(bool b) { io = b; }
void set_hw(bool b) { hw = b; }
void set_other(bool b) { hw = b; }
private:
bool hw; // hardware errors other than IO errors
bool io; // IO errors
bool other; // other errors
};
constexpr
構(gòu)造函數(shù)必須初始化每個(gè)數(shù)據(jù)成員萌焰。初始值設(shè)定項(xiàng)必須使用constexpr
構(gòu)造函數(shù)或者是常量表達(dá)式。
constexpr
構(gòu)造函數(shù)用于生成constexpr
類型的對(duì)象以及constexpr
函數(shù)中的參數(shù)或返回類型谷浅。
Code:
constexpr Debug io_sub(false, true, false); // debugging IO
if (io_sub.any()) // equivalent to if(true)
cerr << "print appropriate error messages" << endl;
constexpr Debug prod(false); // no debugging during production
if (prod.any()) // equivalent to if(false)
cerr << "print an error message" << endl;
參考文獻(xiàn)
[1] Lippman S B , Josée Lajoie, Moo B E . C++ Primer (5th Edition)[J]. 2013.