C 建構函式與析構函式

2021-09-27 07:24:43 字數 4772 閱讀 1044

一、建構函式

(一)建構函式基本性質

(二)定義建構函式形式

(三)利用建構函式建立物件

二、成員初始化表

三、預設引數的建構函式

四、過載建構函式

五、拷貝建構函式

(一)自定義拷貝建構函式

(二)預設的拷貝建構函式

(三)呼叫拷貝建構函式的三種情況

(四)淺拷貝和深拷貝

建構函式和析構函式都是類的成員函式,但它們都是特殊的成員函式,執行特殊的功能,不用呼叫便自動執行,而且這些函式的名字類的名字有關。

c++有一些成員函式特殊性質,這些成員函式負責物件建立、刪除。特殊在於:能夠自動呼叫可以由編譯器自動隱含呼叫。其中一些函式呼叫格式採用運算子函式過載的語法。

c++引進乙個自動完成物件初始化過程的機制,這就是類的建構函式。

物件的初始化:

1.類成員不能在宣告類時候初始化;

2.型別物件的初始化:①呼叫public介面,實現:宣告類->定義物件->定義public函式

②通過建構函式constructor,實現:宣告類->定義物件->定義物件過程中並給成員進行賦值

建構函式是一種特殊的成員函式,它主要用於為物件分配空間,進行初始化。

(一)建構函式的基本性質

(1)建構函式名字必須與類名相同

(2)除了無引數的建構函式是預設建構函式外,帶有全部預設引數值的建構函式也可以是預設建構函式。

(3)建構函式可以有任意型別引數,但不能指定返回型別。它有隱含的返回值,該值由系統內部使用。

(4)預設建構函式的構造物件時不提供引數的建構函式。

(5)建構函式是特殊的成員函式,函式體可寫在類體內,也可以寫在類體外。

(6)在宣告類時如果沒有定義類的建構函式,編譯系統就會在編譯時自動生成乙個預設形式的建構函式。

(7)建構函式可以過載,即乙個類中可以定義多個引數個數和引數型別不同的建構函式,建構函式不能繼承。

(8)建構函式被宣告為公有函式,但它不能像其他成員函式那樣被顯式呼叫,它在定義物件的同時被呼叫。

(9)呼叫順序:在物件進入其作用域時(物件使用前)呼叫建構函式。

(10)自動呼叫:建構函式在定義類物件時自動呼叫,不需使用者呼叫,也不能被使用者呼叫,在物件使用前呼叫。

作用:賦予初值,初始化物件的資料成員,編譯器進行呼叫。

1.定義建構函式的一般形式

class 類名;

類名::類名(形參表)

2.利用建構函式建立物件

(1)利用建構函式之間建立物件,一般形式為:類名 物件名[(實參表)];

「類名」與建構函式相同名,「實參表」建構函式提供的實際引數

#includeusing namespace std;

class date;

date::date(int y,int m,int d)

void date::setdate(int y,int m,int d)

inline void date::showdate()

常量型別和引用型別的資料成員,不能在建構函式中用賦值語句直接賦值,c++有提供初始化表進行置初值。

有成員初始化表的建構函式形式:

類名::建構函式名([參數列])[:(成員初始化表)]

void print()

int getx()

int gety()

private:

int x,y;

};int main()

box();

int volume();

private:

int height,width,longs;

};box::box()

int box::volume()

int main();

類名:: 類名(類名 &物件名) //拷貝建構函式的實現

#includeusing namespace std;

class copyfun

void show()

copyfun(const copyfun &c)

void show()

ca(const ca& c)

void show(), 如果呼叫foo(obj);  首先class_type obj_local(obj) ,這樣就定義了區域性變數obj_local供函式內部使用。

2)引用傳遞

無論對內建型別還是類型別,傳遞引用或指標最終都是傳遞的位址值!而位址總是指標型別(屬於簡單型別), 顯然引數傳遞時,按簡單型別的賦值拷貝,而不會有拷貝建構函式的呼叫(對於類型別).

4.在類中有指標資料成員時,拷貝建構函式的使用

如果在程式設計中不顯示宣告拷貝建構函式的時候,編譯器會自動生成乙個預設拷貝建構函式,而且在一般情況下執行的也很好。但是遇到類有指標資料成員時會有點問題:預設的拷貝建構函式是按成員拷貝構造,這導致有兩個不同的指標(如ptr1=ptr2)指向相同的記憶體。當乙個例項銷毀時,呼叫析構函式 free(ptr1)釋放了這段記憶體,那麼剩下的乙個例項的指標ptr2就無效了,在被銷毀的時候free(ptr2)就會出現錯誤了, 這相當於重複釋放一塊記憶體兩次。這種情況必須顯式宣告並實現自己的拷貝建構函式,來為新的例項的指標分配新的記憶體。

5.拷貝建構函式不受private限制,操作還是自己類的成員變數。

6.什麼是拷貝建構函式?

x::x(const x&); //拷貝建構函式

x::x(x);

x::x(x&, int a=1); //拷貝建構函式

x::x(x&, int a=1, int b=2); //拷貝建構函式

解答:對於乙個類x, 如果乙個建構函式的第乙個引數是下列之一:

a) x&

b) const x&

c) volatile x&

d) const volatile x&

且沒有其他引數或其他引數都有預設值,那麼這個函式是拷貝建構函式.

7.類中可以存在超過乙個拷貝建構函式

class x ;
類可以構造超過乙個的拷貝建構函式

注意,如果乙個類中只存在乙個引數為 x& 的拷貝建構函式,那麼就不能使用const x或volatile x的物件實行拷貝初始化.

如果乙個類中沒有定義拷貝建構函式,那麼編譯器會自動產生乙個預設的拷貝建構函式。

這個預設的引數可能為 x::x(const x&)或 x::x(x&),由編譯器根據上下文決定選擇哪乙個。

以string類為例:

class string

private:

char *m_data;};

//建構函式

string::string(const char* str)

else

} //拷貝建構函式,無需檢驗引數的有效性

string::string(const string &rhs)

//賦值函式

string& string::operator=(const string &rhs)

類string 拷貝建構函式與普通建構函式的區別是:在函式入口處無需與 null 進行比較,這是因為「引用」不可能是null,而「指標」可以為null。(這是引用與指標的乙個重要區別)。然後需要注意的就是深複製了。 

相比而言,對於類string 的賦值函式則要複雜的多:

1.首先需要執行檢查自賦值

防止自賦值以及間接賦值,如:b=a;c=b;a=c;等,如果不進行自檢的話,後面需要delete將會進行報錯的操作,後面隨之的拷貝操作也會報錯。自檢是檢查位址,而不是內容,記憶體位址是唯一的。必須是if(this==&rhs)

2.釋放原有的記憶體資源

必須要用delete釋放掉原有的記憶體資源,如果不釋放原有記憶體資源,該變數指向的記憶體位址將不會是原有的記憶體位址,也無法進行記憶體釋放,造成記憶體洩露。

3.分配新的記憶體資源,並複製資源

記憶體位址變了,但是記憶體位址裡的資源是一樣。

4.返回本物件的引用

目的是為了實現像a=b=c,這樣的鏈式表達,注意返回的是*this。

但仔細一想,上面的程式沒有考慮到異常安全性,我們在分配記憶體之前用delete 釋放了原有例項的記憶體,如果後面new 出現記憶體不足丟擲異常,那麼之前delete 的 m_data 將是乙個空指標,這樣很容易引起程式崩潰,所以我們可以調換下順序,即先 new 乙個例項記憶體,成功後再用 delete 釋放原有記憶體空間,最後用 m_data 賦值為new後的指標。

接下來說說拷貝建構函式和賦值函式之間的區別。

拷貝建構函式和賦值函式非常容易混淆,常導致錯寫、錯用。拷貝建構函式是在物件被建立是呼叫的,而賦值函式只能在已經存在了的物件呼叫。看下面**:

string a("hello");

string b("world");

string c = a;//這裡c物件被建立呼叫的是拷貝建構函式

//一般是寫成 c(a);這裡是與後面比較

c = b;//前面c物件已經建立,所以這裡是賦值函式

上面說明出現「=」的地方未必呼叫的都是賦值函式(算術符過載函式),也有可能拷貝建構函式,那麼什麼時候是呼叫拷貝建構函式,什麼時候是呼叫賦值函式你?判斷的標準其實很簡單:如果臨時變數是第一次出現,那麼呼叫的只能是拷貝建構函式,反之如果變數已經存在,那麼呼叫的就是賦值函式。

c 建構函式與析構函式

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

C 建構函式與析構函式

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

C 建構函式與析構函式

建構函式 對於c 的建構函式,暫且將其分為以下幾類 1.預設建構函式 2.隱士轉換建構函式 3.拷貝建構函式 4.其它建構函式 1.預設建構函式表示沒有任何引數的建構函式,當自定義任何建構函式以後,將不再自動建立預設建構函式,當然,預設建構函式啥也不幹,程式設計師關心係數頓時大跌。關於預設建構函式還...