C 學習筆記(九) 類的建構函式

2021-06-23 07:12:13 字數 3124 閱讀 6101

建構函式 是特殊的成員函式, 

只要建立類型別的新物件, 都要執行建構函式。 建構函式的工作是保證每個物件的資料成員具有合適的初始值。  

如下面:

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 成員函式定義...