一、建構函式
初始化函式應該是一種特殊的成員函式,能夠在建立物件時被自動呼叫。這就是建構函式。
建構函式的名字和類名字相同,它沒有返回值型別(注意:不是void型別)。建構函式的引數通常為資料成員提供初始值。建構函式可以過載,在建立物件時,編譯器會根據初始值的型別和個數來呼叫相應的建構函式,因而建構函式的形式決定了初始化物件的方式。
1.預設建構函式
可以不提供實參就能呼叫的建構函式稱為預設建構函式。在很多情況下可能不便為物件提供初始值。例如:
x ax[10]; 這裡需要呼叫x()來初始化陣列的每個元素,如果x類沒有預設建構函式,就會產生編譯錯誤。通常需要為類定義乙個預設建構函式,在定義物件時如果沒有提供初始值會呼叫預設建構函式進行初始化。預設建構函式可以是沒有形參的建構函式,也可以有形參但每個引數都有預設值。
如果乙個類沒有定義任何建構函式,編譯器會在需要時生成乙個預設建構函式。類中一旦定義了建構函式,即使不是預設建構函式,編譯器也不再自動生成。
2.成員化列表
成員r是引用型別,不能用賦值的形式初始化。對於const資料成員和類型別的資料成員存在類似問題。
初始化由建構函式完成,引用成員的初始化也應該在建構函式中,但是又不能在函式中使用賦值顯示初始化。針對這種特殊的情況有一種特殊的語法,稱為建構函式初始化列表。初始化列表的形式如下:
成員1(初始值1)[,成員2(初始值2),·······]
初始化列表位於建構函式的參數列之後,函式體之前:
建構函式(參數列):初始化列表
例如:class x
3.型別轉換建構函式
帶乙個引數
的建構函式也被看做是進行型別轉換的函式,它可以將引數型別的資料轉換為類型別。在需要隱式型別轉換時編譯器會自動呼叫轉換建構函式。例如:
class x//轉換建構函式,可以將int轉換為x型別
void f(x obj){}
int main()
int iv=10;
f(iv);//ok,呼叫x(int)進行隱含的引數型別轉換
如果不希望編譯器自動進行這種型別轉換,可以在建構函式的宣告前面加上
explicit
關鍵字,禁止隱式轉換。 4.
拷貝建構函式 用
a初始化
b時需要乙個建構函式x(
x&),稱為拷貝建構函式。如果類中沒有定義這樣的建構函式,編譯器會自動生成乙個,預設的行為是按成員拷貝。如果
x是上面定義的只包含簡單資料成員類,這種按成員拷貝的行為可以適用。
x b(a)
就是用a
中的每個成員分別去初始化
b的每個對應的成員,這種行為成為
淺拷貝。(
普通的數值賦值
-淺拷貝)
深拷貝:
x(const x& a):m(a.m),r(m),p(&m){}//
拷貝建構函式
拷貝建構函式的一般形式是x(
x&)或者x
(const x&),
這兩種形式是有差別的。如果拷貝建構函式是x(
x&),那麼就不能用
const
物件來初始化另乙個x型別的物件,因為引數型別不匹配。如果是x(
const x&
),那麼既可以用
const
物件也可以用非
const
物件來初始化另乙個
x型別的物件。 以下
3種情況都是用乙個物件初始化另乙個同類物件的語義,會呼叫拷貝建構函式: (
1)用乙個物件顯式或者隱式初始化另乙個同類物件。 (
2)函式呼叫時,按傳值方式傳遞物件引數。 (
3)函式返回時,按傳值方式返回物件。
需要注意的是,按引用傳遞物件或返回物件時並不是建立和初始化新物件的語義,因而不會引起拷貝建構函式的呼叫。 5.
建構函式中的
this指標
成員函式隱含的第乙個引數是
this
指標,x
類成員函式的
this
指標型別是x*
。this
指標是乙個常量,用於表示當前物件的位址。
如果是在類的普通成員函式中,
this
指向當前正在接收訊息的物件。
如果是在類的建構函式中,
this
指向正在被建立的新物件,當前它還是一塊沒有完成初始化的記憶體區域,建構函式的作用就是正確地初始化該記憶體區域。
二、析構函式
c++中,由析構函式負責物件生存期結束時返回相關資源和自動釋放資源。當物件離開作用域時,或者用
delete
釋放堆上的物件時,析構函式都會被自動呼叫。析構函式的名字是類名字前加上波浪線
「~」。析構函式沒有返回型別,也沒有任何引數。析構函式不能過載,只能為乙個類定義唯一乙個析構函式。
~vector
();//
析構函式
一般情況下,如果乙個類值包含按值儲存的資料成員,則無須析構函式。析構函式主要被用來放棄在類物件的建構函式或生存期中獲得的資源,如釋放互斥鎖或歸還
new分配的空間。不過,析構函式的作用並不侷限在釋放資源上,一般地,析構函式可以執行類設計者希望在最後一次使用物件之後執行的任何操作。
析構函式在大多數情況下都是被自動隱式呼叫的,但有時需要顯示呼叫析構函式。最典型的情況是在使用定位
new的時候。
三、建構函式和析構函式的呼叫
何時呼叫建構函式?
ø 建立全域性物件或區域性物件時,根據初始值的型別和個數呼叫相應的建構函式。
ø 建立類型別的陣列時,呼叫預設建構函式初始化每個陣列的元素。
ø 函式引數按值傳遞物件和按值返回物件時,呼叫拷貝建構函式。
ø 用new
在堆上建立物件時,先為物件分配空間,再呼叫建構函式初始化物件,最後返回物件的位址。
ø 在需要隱式型別轉換時,會呼叫型別轉換建構函式。
建立包含成員物件的組合物件時,成員物件的建構函式會先於組合物件的建構函式被呼叫。
如何呼叫析構函式?
ø 物件在離開作用域時自動呼叫析構函式,同一作用域內的物件的析構函式呼叫次序和建構函式的呼叫次序相反。
ø 用delete
刪除堆上的物件時,先呼叫析構函式清除物件,再釋放堆上的空間。
ø 表示式中建立的臨時物件在表示式結束時會呼叫析構函式。
ø 撤銷包含成員物件的組合物件時,先呼叫組合物件的析構函式,再呼叫成員物件的析構函式。
C 建構函式 析構函式 虛析構函式
一般地,建立物件和刪除物件時,父類建構函式 子類建構函式 子類析構函式 父類析構函式。特例 如果用new建立了乙個物件,並將父類的指標指向這個子類的物件,那麼用delete撤銷物件時,系統只執行基類的析構函式,而不執行派生類的析構函式。如果希望按照子類析構函式 父類析構函式的順序執行,那麼應該將基類...
建構函式 析構函式 虛析構函式
說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...
C 中的建構函式 析構函式,虛函式 純虛函式
1 建構函式能不能是虛函式 1.1 從儲存空間角度 虛函式對應乙個vtable 這大家都知道,可是這個 vtable 其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable 來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,怎麼找 vtable 呢?所以建構函式...