建構函式 是特殊的成員函式,
只要建立類型別的新物件, 都要執行建構函式。 建構函式的工作是保證每個物件的資料成員具有合適的初始值。
如下面:
class sales_item };
建構函式的一些特性:
和類的名字一樣,
沒有返回值, 可以有形參,也可以沒有形參
建構函式的過載:
但有個問題是,我們如何知道應該定義哪個或多少個建構函式?
根據需要制定的方式來建構函式,必要時可以新增
系統根據實參來決定使用哪個建構函式。
建構函式自動執行:
只要建立該型別的乙個物件, 編譯器就執行乙個建構函式。
建構函式不能宣告為const, 如:
class sales_item ;
建構函式的初始化式:
與其它任何函式一樣,建構函式具有名字、行參表和函式體。 但與其它函式不同的是, 建構函式也可以包含乙個建構函式初始化列表:
sales_item :: sales_item (const string &book): isbn(book), units_sold(0), revenue(0.0) {}
建構函式可以定義在類的內部或外部, 建構函式初始化式只在建構函式的定義中而不是宣告中指定。
一些隱式初始化:
sales_item::sales_item(const string &book)
從概念 上講, 可以認為建構函式分兩個階段執行: 1 初始化階段, 2 普通的計算階段, 計算階段由建構函式體中的所有語句組成
在建構函式初始化列表中沒有顯示提及的每個成員, 使用與初始化變數相同的規則來進行初始化:
內建或復合型別的成員的初始值依賴於物件的作用域: 在區域性作用域中這些成員不被初始化,而在全域性作用域中它們被初始化為0。
有時需要建構函式初始化列表:
有些成員必須在建構函式中進行初始化。 對於這樣的成員,在建構函式函式體中對它們賦值不起作用。
其中包括:沒有預設建構函式的類型別的成員,以及const或引用型別的成員。
如:
class constref ;
// 錯誤的賦值方法:
constref::constref(int ii)
正確的賦值方法:
constref:: constref(int ii) : i(ii), ci (ii), ri(i){}
其實, 初始化和賦值 嚴格來講都是低效率的; 資料成員可能已經被直接初始化了, 還要對它進行初始化和賦值。
但是,某些類成員 必須得初始化 如const 或引用型別成員,以及 沒有預設建構函式的類型別的任何成員
初始化 最好不要用乙個類成員來初始化另乙個類成員
初始化式可以是任意表示式
如: sales_item (const std::string &book, int cnt, double price):
isbn(book), units_sold(cnt), revenue(cnt * price) {}
這裡,由於string是乙個類,因此 book是類型別成員,
類型別的資料成員的初始化式:
如: sales_item (): isbn(10, '9'), units_sold(0), revenue(0,0){}
預設的建構函式:
1 合成的預設建構函式:
當有類型別的成員變數時,就出現了合成的預設建構函式。
內建和復合型別的成員,如指標和陣列, 只對定義在全域性作用域中的物件才初始化, 也就是如果定義在main函式中的物件,就可以不初始化。 這是因為,定義在全域性中的變數一般都是靜態編譯的,而不是動態執行的,它是需要儲存在堆或者靜態區的。因此,必須得初始化 。
此外, 每個建構函式應該為每個內建或復合型別的成員提供初始化式,沒有初始化式的成員處於未定義的狀態。
除了作為賦值的目標之外,以任何方式使用乙個未定義的成員都是錯誤的。如果每個成員的狀態已知, 則可以區分空物件和具有實際值的物件。
類通常應定義乙個預設建構函式:
如果乙個類定義了建構函式,那麼編譯器將不合成預設建構函式。 nodefault沒有預設建構函式,意味著:
1 必須通過定義的建構函式來顯示的初始化nodefault成員
2 編譯器不會為具有nodefault型別成員的類合成預設建構函式。 如果這樣的類希望提供預設建構函式,就必須顯示地定義
3 nodefault型別不能用作動態分配陣列的元素型別
4 nodefault 型別的靜態分配陣列必須為每個元素提供乙個顯示的初始化。
5 不能與容器結合使用
隱式類型別轉換:
這個是說,當我們呼叫某個類的函式時,我們向這個函式傳遞了乙個引數,而該類的物件會首先呼叫它的建構函式,該建構函式有可能一句這個傳遞的引數來進行初始化物件, 而後,當該函式結束,時, 構造的該物件就不能再訪問了,它是乙個完全丟棄的物件。
1 抑制由建構函式定義的隱式轉換:
可以通過 將建構函式宣告為explicit, 來防止在需要隱式轉換的上下文中使用建構函式:
class sales_item
explicit sales_item(std::istream &is); }
explicit 關鍵字只能用於類內部的建構函式宣告上。
定義了explicit的建構函式的類, 如果再直接沒有初始化而給函式傳遞乙個引數,可能就不行了。
2 為轉換而顯示地使用建構函式:
string null_book = "9-99-99999-9";
item.same_isbn(sales_item(null_book); // 那就只能通過這種方式 來給函式傳遞引數了。
類成員的顯示初始化:
對於沒有定義建構函式並且其全體資料成員
均為public類, 可以採用如下方式:
結構體的初始化:
struct data ;
都初始化為0
data vall = ;
但是, 顯示初始化類型別物件的成員有三個重大的缺點:
1 要求類的全體資料成員都是public
2 程式設計師的工作加重了
3 如果增加和刪除乙個成員,那麼所有初始化的物件都要更新。
最佳方式,要定義乙個預設建構函式, 允許編譯器自動執行那個建構函式。 以保證每個類物件在初次使用之前正確地初始化。
C 學習筆記 類的建構函式
之前我講了一下關於類的成員函式相關的內容c 學習筆記 類的成員函式的宣告與定義 今天學習的類的建構函式是一種特殊的成員函式!建構函式是用於給類的資料成員進行初始化的!類的建構函式定義和宣告的時候需要注意的幾點是 建構函式的名字必須和類的名字一模一樣 建構函式沒有任何返回值 建構函式的內部可以是空的,...
C 學習筆記 建構函式
在建立某個類的物件時,由於對該物件的狀態 資料 不很明確,因此需要對其進行初始化。例如,我們要在長方形中建立乙個物件,或者說新建乙個長方形,那麼我們首先要確定它的長和寬,假如我們無法確定它的長和寬,那麼我們是無法構造出乙個長方形來的。例如,我們要構造乙個長方形,由於建構函式要在建立新物件時使用,因此...
C 類建構函式 析構函式 學習筆記
1 類的建構函式 類的建構函式是類的一種特殊的成員函式,它會在每次建立類的新物件時執行 建構函式的名稱與類的名稱是完全相同的,並且不會返回任何型別,也不會返回 void 建構函式可用於為某些成員變數設定初始值。include using namespace std class line 成員函式定義...