前言
在我們構建乙個類之後即使我們在其中不定義任何的成員函式,編譯器也會自動生成6個預設的成員函式
1、建構函式
2、析構函式
3、拷貝建構函式
4、賦值運算子過載函式
5、對普通物件取位址運算子過載
6、對常物件取位址運算子過載
這些函式完成了類的基本功能:包括物件的初始化,物件銷毀後的清理工作等。
當然這些自動生成的成員函式功能有限有時候或許無法達到預期的效果,因此我們可以對其進行過載讓其能夠達到我們需要的功能。
建構函式是在類例項化建立出物件時自動進行呼叫的,主要負責物件的初始化。
注意:建構函式只是完成物件的初始化工作,並不為物件開闢空間。
特性建構函式名和類名相同
類例項化物件時自動呼叫
沒有返回值
支援函式過載
預設建構函式
預設建構函式不僅僅是編譯器預設生成的建構函式
1.編譯器預設生成的無參建構函式(前提:使用者沒有顯示定義建構函式)
2.自定義的無參建構函式
3.自定義的全預設建構函式
舉個栗子幫助理解:
建構函式-
>完成物件的初始化工作(與類名相同、例項化自動呼叫、無返回值、支援過載)
class
date
無參建構函式(沒有顯示定義建構函式,則編譯器會自動生成乙個預設的無參建構函式)
注意:預設生成的無參建構函式針對內建型別的成員變數沒有做處理
注意:預設生成的無參建構函式針對自定義型別的成員變數,呼叫建構函式完成初始化
/*date()*/
void
print()
private
:int _year;
int _month;
int _day;};
intmain()
注意:為了避免歧義,乙個類中只能出現乙個預設建構函式,另外自動生成的預設無參建構函式,不會進行內建型別成員變數的初始化,我們往往需要過載。
析構函式是在物件銷毀時自動呼叫的,主要負責物件的資源清理工作(建立物件時分配的空間等)
注意:析構函式只是完成物件資源清理的工作,並沒有進行物件的銷毀。
特性析構函式名是在類名前加~
無返回值、無引數(析構函式無法過載)
乙個類有且只有乙個析構函式(若未顯式定義則會生成預設析構函式)
物件銷毀時自動呼叫析構函式
預設析構函式
若使用者未顯式定義析構函式,則編譯器會自動生成乙個預設析構函式。
預設析構函式:針對內建型別不做處理,針對自定義型別會呼叫對應的析構函式完成清理。
舉個栗子幫助理解:
class
stack
析構函式(後進先析構)
使用者顯示定義析構函式後,編譯器不再生成預設析構函式
~stack()
void
push
(int x)
;void
pop();
size_t size()
;private
:int
* _array;
int _size;
int _capacity;};
intmain()
拷貝構造是用來例項化與某一物件相同的物件的函式
它會將該物件的資料完全複製乙份相同的出來,拷貝構造其實是建構函式的乙個過載。
特性拷貝建構函式名與類名相同
拷貝構造是建構函式的過載形式
拷貝建構函式的引數只有乙個且必須使用引用傳參(傳值會引發無窮遞迴)
無窮遞迴的原因:呼叫就是拷貝構造 ,呼叫函式時要先傳參 ,傳參的過程又是乙個拷貝構造(拷貝構造中呼叫拷貝構造)
預設拷貝構造
使用者未顯示定義拷貝構造則編譯器會自動生成拷貝構造(但是只能完成簡單的淺拷貝)
淺拷貝:將物件按照位元組乙個乙個進行拷貝
物件銷毀會呼叫析構函式,可能會導致同一塊空間被釋放兩次而導致程式崩潰。
如果我們想要對複雜的如鍊錶類進行拷貝構造,則需要自己定義
舉個栗子幫助理解:
class
date
// date d2(d1):物件初始化時自動掉用拷貝構造
// 拷貝構造傳引用:date& d2 = d1;
date
(const date& d)
void
print()
private
:int _year;
int _month;
int _day;};
intmain()
賦值運算子過載是類似於拷貝構造的預設建構函式,不過是將拷貝構造通過 「=」 來使用。
賦值運算子過載是為了使自定義型別像內建型別一樣去使用賦值運算子。
如果使用者未顯式定義賦值運算子過載,那麼編譯器將會生成乙個預設賦值運算子過載(也只是完成淺拷貝),同時這個預設運算子過載是有返回值的,為了實現連續賦值。
推薦傳參和返回值都用引用型別,這是為了防止連續賦值時呼叫拷貝構造出現問題,並且避免多餘的拷貝構造發生可以提高效率。
舉個栗子幫助理解:
//賦值運算子過載,自動生成的過載與他相同
student&
operator=(
const student& stu)
intmain()
我們有時會定義常物件,即不可改變的物件,但是常物件如果呼叫普通成員函式則會出現問題(許可權放大)。
常物件本身不可改,在傳給隱式this的時候這裡的this的型別也應該為const *,否則就會出現型別限定導致呼叫失敗的問題。那麼我們怎麼樣解決呢?這裡就要用到常成員函式。
舉個栗子幫助理解:
class
date
// const修飾*this 指向的物件
void
print()
const
// const date *p1:修飾*p1 指標指向的內容
// date const *p2:修飾*p2 指標指向的內容
// date* const p3:修飾 p3 指標本身
private
:int _year;
int _month;
int _day;};
// 物件呼叫成員函式
void
func
(const date& d)
intmain()
在成員函式後加const將其變為常成員,常成員會將函式的形參this型別改為const *,這樣在常成員函式中則不可再修改呼叫物件的資料。
這兩個預設成員函式是最後的兩個會預設生成的成員函式,一般情況下不需要我們顯式定義,除非我們想讓別人通過取位址符獲得指定的資料。
舉個栗子幫助理解:
student*
operator&(
)const student*
operator&(
)const
c 類的預設六個成員函式
c 中預設的六個成員函式分別是 建構函式,拷貝建構函式,賦值操作符過載函式,析構函式,取位址操作符過載函式,const修飾的取位址操作符過載函式。一 建構函式 1,建構函式是乙個特殊的成員函式,名字與類同名,建立類型別物件時由編譯器自動呼叫,保證每個資料成員都有乙個合適的初始值,並且在物件的生命週期...
類和物件及類中的六個預設的函式
一 物件導向的三大特徵 1 封裝 2 繼承 3 多型 二 類和物件的區別 答 類是抽象的,物件是具體的,所以類不占用記憶體,而物件占用記憶體。三 類和struct的區別 1 struct中預設為public 2 類中預設為private 四 生成物件的2步 1 申請記憶體 2 使用建構函式進行初始化...
類的六個預設成員函式
類的六個預設成員函式 1.建構函式 2.拷貝建構函式 3.析構函式 4.賦值操作符過載 5.取位址操作符過載 6.const修飾的取位址操作符過載 建構函式 是乙個特殊的成員函式,名字與類名相同,建立類型別物件時,由編譯器自動呼叫,在物件的生命週期內隻且只呼叫一次,以保證每個資料成員都有乙個合適的初...