C 建構函式與析構函式

2021-09-08 11:12:24 字數 3141 閱讀 4916

**

建構函式

對於c++的建構函式,暫且將其分為以下幾類:

1. 預設建構函式

2. 隱士轉換建構函式

3. 拷貝建構函式

4. 其它建構函式

1. 預設建構函式表示沒有任何引數的建構函式,當自定義任何建構函式以後,將不再自動建立預設建構函式,當然,預設建構函式啥也不幹,程式設計師關心係數頓時大跌。關於預設建構函式還需要關心的乙個問題是,當本類繼承於另乙個類(即父類),父類沒有預設建構函式時,本類將自動沒有建構函式,並且還必須定義至少能夠支援父類初始化的建構函式。

2. 隱士轉換建構函式時什麼呢?它是這樣一類建構函式,這類建構函式僅含有乙個引數。由於c++規定,為只含有乙個引數的建構函式自動定義一種隱士轉換,將建構函式的引數對應資料型別的物件轉換為類物件。如下面例子所示:

1

class

string ;

45 string s = "

hello friends

";

其中字串「hello friends」通過隱士轉換建構函式轉換為了string類物件s。這裡不得不提乙個關鍵字explicit,比較悲劇的是學了好幾年c++後才知道這麼乙個關鍵字,這也充分體現了一本好書的重要性。下面來看看explicit的用法,再解釋。

1

class

string ;

45 string s = "

hello friends

"; //

編譯不通過

67 string s("

hello friends

"); //

編譯通過

explicit僅用於建構函式,且僅用於隱士轉換建構函式,其目的是禁止隱士建構函式功能。如上**所示,當為建構函式新增explicit關鍵字後,string s = "hello friends"; 編譯不通過。當然,此時建構函式本身還是能夠正常工作的。

3. 拷貝建構函式,就是用來複製物件的一種特殊的建構函式。通過它,可以使用乙個已經建立好的物件(由拷貝建構函式的引數指定)去初始化乙個正準備建立的同類物件。

1

class類名2

;

如上述**所述,拷貝建構函式只能有乙個引數,並且必須是同類物件的引用。每個類都應該有乙個拷貝建構函式,如果使用者沒有指定,將使用預設的拷貝建構函式。預設拷貝建構函式執行物件的全部內容複製,但有時需要有選擇、有變化地複製。這種情況就需要顯示定義拷貝建構函式,並實現為感興趣部分的複製或者為新物件新增某些屬性值。

拷貝建構函式最常見的使用方式是在類中含有指標型別屬性時,因為預設的拷貝函式是按指拷貝的,即所謂的淺拷貝。這時需要顯示定義拷貝建構函式,並顯示地將指標從新分配記憶體並copy以前指向的值到新分配的記憶體中。

4. 其它建構函式,沒什麼特別的,就是前面1,2,3未包含的建構函式均屬於該類。

建構函式初始化引數列表

以下情況下需要使用初始化成員列表:(待補充)

一、需要初始化的資料成員是物件的情況;

二、需要初始化const修飾的類成員;

第一種情況,如果類a中屬性存在乙個類b,且類b沒有不帶引數的建構函式,此時初始化a時也需要初始化b,所以需要初始化引數列表。當然,此種情況一般成員屬性也可以通過此種方式初始化。

第二種情況,const成員屬性不能複製,一旦初始化後就不能改變。

下面的例子說明建構函式初始化引數列表的使用:

1 #include 2

using

namespace

std;34

classb5

10};

1112

classa13

;2324 a::a(int a, int ci):b(a),ci(ci),c(4

) 27

28int

main()

29

析構函式

析構函式就與建構函式對應,在物件消亡時做一些善後處理。看下面的例子:

1 #include 2

using

namespace

std;34

classa5

10 ~a()

13};

1415

class b : publica16

21 ~b()

24};

2526

intmain() "

font-family: arial, verdana, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);

">

編譯輸出:

1 # ./a.out

2a...

3b...

4 ~a

由此可見,在物件a消亡時,會自動呼叫物件a的析構函式。但是c++也太傻了吧,明明我例項化的b物件,可為啥析構時是呼叫a物件的析構函式呢?看delete a,由此可估計delete關鍵字只認a的物件,而不會變通。怎麼能夠這樣...

virtual關鍵字

上面的例子顯示,構造了物件b,卻沒有析構,這會造成啥問題呢?反正我是不清楚了。於是c++提供的virtual關鍵字可以解決這個問題,看下面的**:

1 #include 2

using

namespace

std;34

classa5

10virtual ~a()

13};

1415

class b : publica16

21 ~b()

24};

2526

intmain()

輸出:

1 # ./a.out

2a...

3b...

4 ~b

5 ~a

可見,新增virtual關鍵字後,確實能夠解決該問題,b物件也呼叫了析構函式。可是這是為什麼呢?

下面開始yy了,也許delete並不是那麼傻,她會去虛函式表裡面檢視當前析構函式是否被定義為虛函式,如果是虛函式,它就會想了,那物件會不會例項化的是子類的物件呢,於是再判斷是否例項化為子類物件,如果是就先呼叫子類的析構函式。

c 建構函式與析構函式

一 建構函式 c 提供建構函式來處理物件的初始化,建構函式是一種特殊的成員函式,與其他的成員函式不同,不需要使用者來呼叫他,而是在建立物件時自動執行。它的特點是 函式名和類名相同,沒有返回值,可以過載 如果程式中未宣告,則系統自動產生出乙個預設的建構函式,預設的建構函式時不帶引數的。比如 stude...

C 建構函式與析構函式

c 規定,每個類必須有預設的建構函式,沒有建構函式就不能建立物件。若沒有提供任何建構函式,那麼c 提供自動提供乙個預設的建構函式,該預設建構函式是乙個沒有引數的建構函式,它僅僅負責建立物件而不做任何賦值操作。只要類中提供了任意乙個建構函式,那麼c 就不再自動提供預設建構函式。類物件的定義和變數的定義...

c 建構函式與析構函式

1.建構函式 建構函式 是一種特殊的方法。主要用來在建立物件時初始化物件,即為物件成員變數賦初始值,總與new運算子一起使用在建立物件的語句中。如果建立乙個類你沒有寫任何建構函式,則系統會自動生成預設的無參建構函式,函式為空,什麼都不做只要寫了乙個其他的某一種建構函式,系統就不會再自動生成這樣乙個預...