C C 自學旅程 8 建構函式和析構函式

2022-09-14 01:42:12 字數 3399 閱讀 3410

新引入了類這個概念,你別說突然之間各種概念就多起來麻煩起來了。今天來說說建構函式和析構函式。

一、建構函式和拷貝建構函式

1. 建構函式

簡單的說,建構函式就是給類成員初始化的函式。那怎麼使用呢?我們直接上**:

1

//建構函式

2 #include3

using

namespace

std;

4class

date5;

1314 date::date(int x, int y, int

z):day(z)

1519 date::date():year(1),month(1)20

23int

date::output()

2427

intmain()

28

看**說話,重點易錯內容用圓圈序號標出:

第8、9行的date(int, int, int)和date(int)這兩個函式就是建構函式,可以發現它與類型別名相同,①建構函式名只能和類型別名相同,且宣告時都不能標函式型別(void也不能標)

看到第14到23行,這裡是函式的定義,寫明了函式要做什麼事情:主要就是初始化賦值。②定義時也不能標註函式型別,同時也不可以有返回值。③建構函式可以有引數也可以沒有引數。這個小程式這裡使用了函式過載,④建構函式也可以使用函式過載,呼叫時根據呼叫的方式確定到底是哪個。在定義建構函式時可以看出,⑤給變數賦值有兩種方式,即在參數列圓括號後的「:」後面寫變數(值),或是一般的在函式體中間寫,執行的順序是初始化區域→函式體。

接下來說說怎麼呼叫建構函式。建構函式不需要手動呼叫,看到第29至30行,⑥建構函式會在定義類變數的時候自動呼叫,呼叫時根據呼叫時的引數**式確定是函式重載重的哪個,特別注意的是定義變數要呼叫沒有引數的建構函式時不要括號,即30行不是「date d2()」而是「date d2」。另外嘞,還可以⑦給已經定義宣告過的變數重新使用建構函式賦值,方法同第32行,注意等號右邊是「date(......)」,即型別名(......)

2. 拷貝建構函式

拷貝建構函式用於使用乙個已經存在的物件來初始化另乙個同型別的物件。它具有唯一引數

1

//構造拷貝函式:例1.

2 #include3

using

namespace

std;

4class

date5;

13 date::date(int x,int y,int

z)14

19 date::date(date &d) //

拷貝建構函式

2025

intdate::output()

2629

intmain()

30//結果:

輸出:2023年2月14日

輸出:2023年2月14日

可以看到拷貝建構函式初始化d2時是跟d1的初始化有關聯的。拷貝建構函式在一下三種情況中會被呼叫:

①乙個物件通過另乙個物件初始化,如上面的例1.

②乙個物件以值傳遞的方式使用

//例2.

void

func(date d)

intmain()

③乙個物件以值傳遞的方式從函式返回

//例3.

date fun2()

intmain()

例2和例3中並沒有出現定義拷貝建構函式,是因為使用者沒有自定義拷貝建構函式,系統會自動弄乙個預設的拷貝建構函式,用於傳值的過程

下面說一下淺拷貝和深拷貝

1

//例4.

2 #include3 #include4

using

namespace

std;

5class

student6;

14student::student()

1521}22

void student::setname(char *n)

2328}29

void

student::outputname()

3033

34int

main()

35

這樣的結果是:

s1: xiaoming

s2: xiaoming

after change

s1: xiaoxin

s2: xiaoxin

因為系統自動建立的拷貝建構函式不會自動新建立乙個空間,讓s2.name指標指向新空間,所以造成的結果是s2name的值隨s1的更改而更改。它倆的name指標指向同乙個空間。

而通過自定義拷貝建構函式使用深拷貝,可以自定義建立乙個新的空間,以解決這個問題。

1

//例5.

2 #include3 #include4

using

namespace

std;

5class

student6;

15student::student()

1622

}23 student::student(student &stu)

2428

void student::setname(char *n)

2934}35

void

student::outputname()

3639

40int

main()

41

這樣一來,每個物件都有獨立的name資源空間,從而避免了使用混亂的情況。

二、析構函式

從上面的例5可以看出,我們用new建立了乙個name的空間,當物件使用完並消亡後,那個建立的空間並沒有用delete刪去,這樣當建立了很多這樣的空間後,記憶體就會不堪重負了,但是每次用完後手動刪除是不是太麻煩了,而且也耗費很大的精力。析構函式就是用於在物件消亡後自動釋放建立的空間的。用法:

//

析構函式取名為「~類名」

public

: ~student();

student::~student()

注意:①析構函式名稱只能是"~類名()",也沒有型別也沒有返回值;②乙個類只能有乙個析構函式,若使用者沒有建立,系統還是自動建立乙個不做事的;③析構函式在物件超出作用域時自動執行。

over!

類String的建構函式 析構函式和賦值函式

海康威視16年春季校招程式設計題目 題目 編寫類string的建構函式 析構函式和賦值函式,已知類string的原型為 class string 解答 1 普通建構函式 建構函式 建構函式是一種特殊的方法,主要用來在建立物件時初始化物件,即為物件成員變數賦初始值,總與new運算子一起使用在建立物件的...

C C 筆記 之建構函式,析構函式

構造方法用來初始化類的物件,與父類的其它成員不同,它不能被子類繼承 子類可以繼承父類所有的成員變數和成員方法,但不繼承父類的構造方法 因此,在建立子類物件時,為了初始化從父類繼承來的資料成員,系統需要呼叫其父類的構造方法。如果沒有顯式的建構函式,編譯器會給乙個預設的建構函式,並且該預設的建構函式僅僅...

建構函式和析構函式

建構函式沒有返回值,不能被顯示的呼叫。它是在定義物件時由系統自動執行的,而且只執行一次。如果沒有定義建構函式,系統會自動生成乙個建構函式,只是這個建構函式的函式體是空,沒有引數,也不執行任何初始化的操作。帶引數的建構函式 有一種簡練,方便的寫法 建構函式的引數初始化表 box int h,int w...