C++構造函數

C++中構造函數是特殊的成員函數,只要定義類的新對象就會執行構造函數,構造函數是保證每個對象的數據成員具有合適的初始值。

構造函數特點:

1)構造函數與類同名,不能指定返回類型,且不能聲明爲const函數,詳見你所不知道的 const

2)構造函數可以重載,所以可以有多個構造函數

	sales_item(void) /*const*/;
	sales_item(istream &is /*= cin */);
	sales_item(const string & book ); //must const 	
	sales_item(const sales_item &org);

3)調用構造函數,使用不同的實參就會調用不同的構造函數,如下

	sales_item sales0;
	sales_item sales1("hello world");  
	sales_item("hello world"); //也可以
	sales_item sales2 = sales_item("123456"); //定義
	sales_item sales3(cin);

構造函數的初始化式:

函數後面可以包含一個初始化列表,原型爲形參後緊跟一個冒號,然後就是以逗號分開的數據成員列表,初始化值放在圓括號內,如下

sales_item::sales_item(void)
	: isbn(1,'0'), units_sold(0), revenue(0.0), a(0), b(a){}
初始化注意之處:

1)構造函數分兩階段進行,初始化階段和普通的計算階段(計算階段就是函數體中的語句或者稱爲賦值階段)

2)未提供顯式初始化的變量使用與初始化變量相同的規則進行初始化,內置或者複合類型依賴於對象的作用域,局部不初始化全局初始化爲0,類類型使用默認的構造函數

3)必須提供初始化列表的情況,如下

screen::screen(void)//contents由string默認構造函數初始化
	: nConstVar(0)/*contents("")*/,cursor(0),height(0),width(0),access_ctr(0){}
const int nConstVar; //必須在直接初始化列表進行初始化,如果在函數體中就會出錯,還有就是引用的初始化,如下
sales_item::sales_item(void)
	: isbn(1,'0'), units_sold(0), revenue(0.0), a(0), b(a){}
int &b; b一定要顯式初始化

4)成員初始化的次序

class x {
	int i;
	int j;
public:
	x(int val):j(val), i(j){};
};
這裏我在vs2012編譯下通過了,顯式初始化次序對這個沒有影響,在gcc version 4.4.1使用g++編譯同樣通過。但是在vs2012調試後發現,i=-858993460,j=1 也就是說其實i並沒有提供的j的值初始化,所以最好嚴格按照初始化順序初始化,儘可能避免使用成員來初始化,最好統一使用形參來進行初始化。

5)類類型的初始化可以使用該類型的任意構造函數,也可以使用默認的構造函數。

6)類成員的顯示初始化,直接初始化成員也是可以的,但是必須滿足一下幾點

a. 類的全體成員必須是public

b. 沒有定義構造函數

如下:

	struct init
	{
		int ival;
		char * ptr;
	};
	init initval = {1, NULL};

默認實參:

1)可以爲構造函數提供默認的實參,但是這個形參後面的所有形參必須提供默認值,所以需要合理調整形參的位置。

2)另外默認值只能提供在類聲明的位置處,不能在定義處提供,否則編譯會出錯。如下

class y
{
public:
	y(ifstream &ifs, const string &str = ""):strVal(str), nVal(0), dVal(NULL), ifsVal(ifs){};
	~y(){};

private:
	const string strVal;
	int nVal;
	double* dVal;
	ifstream& ifsVal;
};
3)可以有默認值,但是提供默認值後有些需要合併的函數就需要刪除,不能出現調用時出現歧義,如下

	sales_item(void) /*const*/;
	~sales_item(void);
	sales_item(istream &is = cin );
	sales_item(const string & book = "" ); //must const 	

這裏就會發現,如果調用sale_item默認不帶形參的構造函數就會出現歧義,不知該調用哪個

默認構造函數:

1)合成的默認構造函數,一個類哪怕只定義一個構造函數,編譯器就不會生成合成默認構造函數

2)合成的默認構造函數使用與變量初始化相同的規則來初始化成員,如果類包含內置類型或者複合類型的成員,則該類不應該依賴於合成的默認構造函數。

3)類通常應該定義一個默認構造函數,只要定義了其他構造函數,提供默認構造函數總是對的

4)使用默認構造函數時,切記不可寫成如下的形式

sales_item item();

這種寫法是錯誤的,因爲這裏其實聲明的item是函數,返回類型是sales_item,但是下面是允許的

    sales_item item1 = sales_item(); //定義
或者

   sales_item* item2 = new sales_item();

隱式轉轉:

當調用構造函數的時候,如果對形參沒有特別說明,就有可能發生隱式轉換,如下

	const string book = "9-99-9999";
	item.same_ishn(book);
這裏就將string轉換爲sales_item類類型,但是有時候卻需要抑制這種轉化,如下

	explicit sales_item(void); // 防止隱式轉換

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