C++在空類下默默編寫並調用了哪些函數

什麼時候empty class不再是個空類呢?當C++處理之後。如果沒聲明,編譯器就會給它聲明一個copy構造函數、一個copy assignment操作符和一個析構函數。此外如果沒有聲明任何構造函數,編譯器也會給你聲明一個default構造函數。所有這些函數都是public且inline。因此,如果你寫下:

class Empty 
{
};

這就好像你寫下這樣的代碼:

class Empty 
{
public:
	Empty() {}								// default構造函數
	Empty(const Empty& rhs) {}				// copy構造函數
	~Empty() {}								// 析構函數
	Empty& operator=(const Empty& rhs) {}	// copy assignment操作符
};

惟有當這些函數被需要,它們纔會被編譯器創建出來。程序中需要它們是很平常的事。下面代碼造成上述每一個函數被編譯器產出:

Empty e1;				// default構造函數
						// 析構函數
Empty e2(e1);			// copy構造函數
e2 = e1;				// copy assignment操作符

• default構造函數和析構函數

default構造函數和析構函數主要是給編譯器一個地方用來放置“藏身幕後”的代碼,像是調用base classes和non-static成員變量的構造函數和析構函數。注意,編譯器產生的析構函數是個non-virtual,除非這個class的base class自身聲明有virtual析構函數

• copy構造函數和copy assignment操作符

copy構造函數和copy assignment操作符,編譯器創建的版本只是單純地將來源對象的每一個non-static成員變量拷貝到目標對象。考慮一個NamedObject template,它允許你將一個個名稱和類型爲T的對象產生關聯:

template <typename T>
class NamedObject
{
public:
	NamedObject(const char* name, const T& value);
	NamedObject(const std::string& name, const T& value);
	...
private:
	std::string nameValue;
	T objectValue;
};

由於其中聲明瞭一個構造函數,編譯器於是不再爲它創建default構造函數。這很重要,意味如果你用心設計一個class,其構造函數要求實參,你就無須擔心編譯器會毫無掛慮地爲你添加一個無實參構造函數(即default構造函數)而遮蓋掉你的版本。
NamedObject既沒有聲明copy構造函數,也沒有聲明copy assignment操作符,所以編譯器會爲它創建那些函數。現在,看看copy構造函數的用法:

NamedObject<int> no1("Smallest Prime Number", 2);
NamedObject<int> no2(no1);							// 調用copy構造函數

編譯器生成的copy構造函數必須以no1.nameValue和vo1.objectValue爲初值設定no2.nameValue和no2.objectValue。兩者之中,nameValue的類型是string,而標準string有個copy構造函數,所以no2.nameValue的初始化方式是調用string的copy構造函數並以no1.nameValue爲實參。另一個成員NamedObject::objectValue的類型是int,那是個內置類型,所以no2.objectValue會以“拷貝no1.objectValue內的每一個bits”來完成初始化。
編譯器爲NamedObject所生的copy assignment操作符,其行爲基本上與copy構造函數如出一轍,但一般而言只有當代碼合法且有適當機會證明它有意義。萬一兩個條件有一個不符合,編譯器會拒絕爲class生出operator=。

• 總結

編譯器可以暗自爲class創建default構造函數、copy構造函數、copy assignment操作符,以及析構函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章