詳解C++中類(lèi)的六大默認(rèn)成員函數(shù)
一、類(lèi)的默認(rèn)成員函數(shù)
二、構(gòu)造函數(shù)Date(形參列表)
構(gòu)造函數(shù)主要完成初始化對(duì)象,相當(dāng)于C語(yǔ)言階段寫(xiě)的Init函數(shù)。
默認(rèn)構(gòu)造函數(shù):無(wú)參的構(gòu)造函數(shù)或全缺省的構(gòu)造函數(shù),二者只能存在一個(gè),同時(shí)存在類(lèi)中,調(diào)用時(shí)會(huì)出現(xiàn)二義性。
1、構(gòu)造函數(shù)的函數(shù)名和返回值
構(gòu)造函數(shù)的函數(shù)名和類(lèi)名相同且無(wú)返回值
2、構(gòu)造函數(shù)的調(diào)用
對(duì)象實(shí)例化時(shí),編譯器自動(dòng)調(diào)用對(duì)應(yīng)的構(gòu)造函數(shù)且只調(diào)用一次
3、構(gòu)造函數(shù)的重載
構(gòu)造函數(shù)可以重載(多種初始化方式)注意:雖然全缺省和無(wú)參的構(gòu)造函數(shù)構(gòu)成重載,但是調(diào)用時(shí)存在二義性。
class Date { public: //構(gòu)造函數(shù)的重載 Date() { } Date(int year,int month,int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; }; int main() { Date d1;//創(chuàng)建并通過(guò)無(wú)參構(gòu)造函數(shù)初始化對(duì)象時(shí),無(wú)需加括號(hào),不然變成了函數(shù)聲明 Date d2(2022,9,23); return 0; }
4、系統(tǒng)生成的默認(rèn)構(gòu)造函數(shù)
如果我們?cè)陬?lèi)中不寫(xiě)構(gòu)造函數(shù),C++編譯器會(huì)在類(lèi)中幫我們生成一個(gè)無(wú)參的構(gòu)造函數(shù)。我們寫(xiě)了構(gòu)造函數(shù),那么系統(tǒng)將不會(huì)生成。
我們構(gòu)造對(duì)象并調(diào)用構(gòu)造函數(shù)時(shí),初始化的數(shù)據(jù)是隨機(jī)值:
5、系統(tǒng)生成的默認(rèn)構(gòu)造函數(shù)的作用
系統(tǒng)生成默認(rèn)構(gòu)造函數(shù)對(duì)內(nèi)置類(lèi)型不處理,對(duì)自定義類(lèi)型調(diào)用他的構(gòu)造函數(shù)。
注意:下方代碼中,Date類(lèi)中的內(nèi)置類(lèi)型將會(huì)調(diào)用Date類(lèi)中的構(gòu)造函數(shù);Date類(lèi)中的Time _t將會(huì)調(diào)用Time類(lèi)中的構(gòu)造函數(shù)。
6、可以在內(nèi)置類(lèi)型的成員變量的聲明中給缺省值
C++11中針對(duì)內(nèi)置類(lèi)型不處理初始化為隨機(jī)值的問(wèn)題,打了補(bǔ)?。簝?nèi)置類(lèi)型成員變量在類(lèi)中聲明可以給默認(rèn)值,甚至可以給動(dòng)態(tài)開(kāi)辟的缺省值,缺點(diǎn)是不能判斷空間是否開(kāi)辟成功。
注意這里的默認(rèn)值是缺省值,不是初始化。初始化是要等對(duì)象調(diào)用時(shí)才叫初始化。
class Date { private: int _year=1; int _month=2; int _day=3; int* arr = (int*)malloc(sizeof(int) * 5); };
這個(gè)特性只能用于解決默認(rèn)構(gòu)造函數(shù)初始化為隨機(jī)值的問(wèn)題。這個(gè)特性不能解決對(duì)象的多種初始化方式(這也是構(gòu)造函數(shù)支持重載的原因),構(gòu)造函數(shù)該寫(xiě)還是得自己寫(xiě)。
7、初始化列表初始化
- 1、對(duì)象的每個(gè)成員變量是在初始化列表部分進(jìn)行初始化,而函數(shù)體內(nèi)的行為是對(duì)成員函數(shù)賦初值。
- 2、如果沒(méi)有在初始化列表里顯示初始化某個(gè)成員函數(shù),對(duì)于內(nèi)置類(lèi)型,有缺省值用缺省值,無(wú)缺省值初始化為隨機(jī)值;對(duì)于自定義類(lèi)型將會(huì)調(diào)用它的默認(rèn)構(gòu)造函數(shù),沒(méi)有找到默認(rèn)構(gòu)造就會(huì)報(bào)錯(cuò)。
- 3、引用、const、無(wú)默認(rèn)構(gòu)造函數(shù)的自定義類(lèi)型必須通過(guò)初始化列表初始化。
- 4、成員變量在類(lèi)中聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先后次序無(wú)關(guān)。
Date(int year=1,int month=1,int day=1)//缺省值 :_year(year)//成員變量的定義 ,_month(month) ,_day(day) {}//成員變量的賦初值
總結(jié):盡量使用使用初始化列表進(jìn)行初始化,在類(lèi)中盡量提供默認(rèn)構(gòu)造函數(shù)(最好是全缺省的默認(rèn)構(gòu)造函數(shù))
8、單參數(shù)構(gòu)造(C++98)、多參數(shù)構(gòu)造(C++11)
class Date { public: Date(int year=1,int month=1,int day=1) :_year(year) ,_month(month) ,_day(day) {} private: int _year; int _month; int _day; }; int main() { //單參數(shù)的構(gòu)造,構(gòu)造+拷貝,編譯器直接優(yōu)化為構(gòu)造C++98 Date d1 = 2022; //臨時(shí)對(duì)象具有常性,構(gòu)造+拷貝,編譯器不會(huì)優(yōu)化 const Date& d2 = 2023; //多參數(shù)的構(gòu)造C++11 Date d3 = { 2022,10,16 }; return 0; }
- 1、在構(gòu)造時(shí),支持等號(hào)加參數(shù)的構(gòu)造形式,實(shí)際上發(fā)生的是隱式類(lèi)型轉(zhuǎn)換。2022由int類(lèi)型隱式類(lèi)型轉(zhuǎn)換為Date型的臨時(shí)對(duì)象,該臨時(shí)對(duì)象再將它的值拷貝構(gòu)造給d1。
- 2、2023會(huì)隱式類(lèi)型轉(zhuǎn)換為Date類(lèi)型的臨時(shí)對(duì)象,具有常屬性。d2是這個(gè)臨時(shí)對(duì)象的引用,所以需要加上const。這里發(fā)生構(gòu)造+拷貝構(gòu)造,涉及臨時(shí)對(duì)象的引用,所以編譯器并不會(huì)發(fā)生優(yōu)化。
- 3、可以使用explicit關(guān)鍵字修飾構(gòu)造函數(shù),會(huì)禁止隱式類(lèi)型轉(zhuǎn)換。
三、析構(gòu)函數(shù)~Date()
析構(gòu)函數(shù):與構(gòu)造函數(shù)功能相反,析構(gòu)函數(shù)不是完成對(duì)對(duì)象本身的銷(xiāo)毀,局部對(duì)象銷(xiāo)毀工作是由編譯器完成的。而對(duì)象在銷(xiāo)毀時(shí)會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù),完成對(duì)象中資源的清理工作。資源包括動(dòng)態(tài)開(kāi)辟的空間,文件的關(guān)閉等。相當(dāng)于C語(yǔ)言階段寫(xiě)的destroy函數(shù)。
1、析構(gòu)函數(shù)的函數(shù)名、參數(shù)和返回值
析構(gòu)函數(shù)的函數(shù)名是類(lèi)名前加~,無(wú)參無(wú)返回值類(lèi)型。
2、析構(gòu)函數(shù)的特點(diǎn)
一個(gè)類(lèi)只能有一個(gè)析構(gòu)函數(shù)。若未顯式定義,系統(tǒng)會(huì)自動(dòng)生成默認(rèn)的析構(gòu)函數(shù)。注意:析構(gòu)函數(shù)不能重載
對(duì)象生命周期結(jié)束時(shí),C++編譯系統(tǒng)系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)
3、編譯器生成的默認(rèn)析構(gòu)函數(shù)
對(duì)于編譯器生成的默認(rèn)析構(gòu)函數(shù),對(duì)自定義類(lèi)型調(diào)用他的析構(gòu)函數(shù)。對(duì)于內(nèi)置類(lèi)型,沒(méi)有需要處理資源。
注意:Date類(lèi)中的內(nèi)置類(lèi)型會(huì)調(diào)用Date類(lèi)中的析構(gòu)函數(shù);Date類(lèi)中的自定義類(lèi)型Time _t會(huì)調(diào)用Time的析構(gòu)函數(shù)。
四、拷貝構(gòu)造Date(const Date& d)
1、拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的重載
拷貝構(gòu)造函數(shù):只有單個(gè)形參,該形參是對(duì)本類(lèi)類(lèi)型對(duì)象的引用(一般常用const修飾),在用已存在的類(lèi)類(lèi)型對(duì)象創(chuàng)建新對(duì)象時(shí)由編譯器自動(dòng)調(diào)用。
拷貝構(gòu)造函數(shù)的函數(shù)名和構(gòu)造函數(shù)相同,無(wú)返回值,在參數(shù)上和構(gòu)造函數(shù)構(gòu)成重載。
2、拷貝構(gòu)造函數(shù)的參數(shù)
拷貝構(gòu)造函數(shù)的參數(shù)只有一個(gè)并且是類(lèi)類(lèi)型對(duì)象的引用。如果使用傳值傳參的方式進(jìn)行拷貝構(gòu)造,在傳值的過(guò)程中實(shí)參需要拷貝一份數(shù)據(jù)給形參,這個(gè)過(guò)程需要調(diào)用拷貝構(gòu)造。形成層層傳值引發(fā)對(duì)象的拷貝的遞歸(有遞無(wú)歸)調(diào)用。
3、若未顯式定義,編譯器會(huì)生成默認(rèn)的拷貝構(gòu)造函數(shù)
默認(rèn)的構(gòu)造函數(shù)對(duì)于內(nèi)置類(lèi)型按照字節(jié)拷貝。對(duì)于自定義類(lèi)型則調(diào)用它的拷貝構(gòu)造函數(shù)。
4、拷貝構(gòu)造函數(shù)的深淺拷貝
通過(guò)默認(rèn)的拷貝構(gòu)造函數(shù)構(gòu)造的對(duì)象,按字節(jié)完成拷貝。這種拷貝被稱(chēng)為淺拷貝(值拷貝)。
int main() { Date d1(2022,9,24); Date d2(d1); return 0; }
對(duì)于內(nèi)置類(lèi)型,使用淺拷貝即可,系統(tǒng)默認(rèn)生成的就可以做到,所以我們不用動(dòng)手寫(xiě)拷貝構(gòu)造函數(shù)。注意這里有d1,d2兩個(gè)對(duì)象,當(dāng)main函數(shù)生命周期結(jié)束時(shí),這兩個(gè)對(duì)象均會(huì)發(fā)生一次析構(gòu),d2先析構(gòu),d1后析構(gòu)。(后定義的先銷(xiāo)毀,類(lèi)似棧的后進(jìn)先出原則)
但是淺拷貝對(duì)于占用“資源”的成員變量時(shí)(例如成員變量中有動(dòng)態(tài)開(kāi)辟或fopen的資源),指針雖然復(fù)制了,但是所指向的內(nèi)容卻沒(méi)有復(fù)制,析構(gòu)時(shí)存在同一塊空間被釋放兩次的問(wèn)題。需要進(jìn)行深拷貝。深拷貝的拷貝構(gòu)造函數(shù)必須自己手動(dòng)實(shí)現(xiàn)。
class Stack { public: Stack(int capacity=100)//構(gòu)造函數(shù) { _capacity = capacity; _top = 0; _arr = (int*)malloc(sizeof(int) * 5); if (_arr == nullptr) { perror("malloc fail"); exit(-1); } } //Stack(const Stack& st)//淺拷貝,棧這個(gè)類(lèi)不能用淺拷貝 //{ // _capacity = st._capacity; // _top = st._top; // _arr = st._arr; //} Stack(const Stack& st)//深拷貝 { _capacity = st._capacity; _top = st._top; _arr = (int*)malloc(sizeof(int) * st._top); if (_arr == nullptr) { perror("malloc fail"); exit(-1); } memcpy(_arr, st._arr,sizeof(int)*st._top); } ~Stack()//析構(gòu)函數(shù) { _capacity = 0; _top = 0; free(_arr); _arr = nullptr; } private: int* _arr; int _top; int _capacity; };
棧這個(gè)類(lèi)因?yàn)槌蓡T變量中有動(dòng)態(tài)開(kāi)辟的空間,所以要用深拷貝。
5、拷貝構(gòu)造函數(shù)調(diào)用場(chǎng)景
- 1、使用已存在的對(duì)象創(chuàng)建新對(duì)象
- 2、函數(shù)參數(shù)類(lèi)型為類(lèi)的類(lèi)型對(duì)象(傳值調(diào)用,實(shí)參拷貝給形參)
- 3、函數(shù)返回值類(lèi)型為類(lèi)的良心對(duì)象(傳值返回)
五、賦值運(yùn)算符重載Date& operator=(const Date& d )
1、賦值運(yùn)算符重載
只有賦值運(yùn)算符是默認(rèn)成員函數(shù)。
2、賦值運(yùn)算符重載的注意事項(xiàng)
- 1、參數(shù)是const T&,傳引用可以減少一次拷貝構(gòu)造。
- 2、返回值是*this的引用,引用返回,減少一次拷貝構(gòu)造,有返回值是為了支持函數(shù)的鏈?zhǔn)皆L問(wèn)。
- 3、務(wù)必檢查下是否支持自己給自己賦值。
- 4、賦值運(yùn)算符重載必須是類(lèi)中的默認(rèn)成員函數(shù),不能寫(xiě)在全局。
- 5、系統(tǒng)默認(rèn)生成的賦值運(yùn)算符重載會(huì)完成值拷貝。
六、取地址操作符重載和const取地址操作符重載
Date* operator&() { return this; //return nullptr; } const Date* operator&()const { return this; //return nullptr; }
不用自己寫(xiě),除非想讓別人通過(guò)取地址操作符獲取到特定值(自己在重載函數(shù)內(nèi)部寫(xiě))或屏蔽類(lèi)地址。
以上就是詳解C++中類(lèi)的六大默認(rèn)成員函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于C++類(lèi)成員函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言中經(jīng)socket接收數(shù)據(jù)的相關(guān)函數(shù)詳解
這篇文章主要介紹了C語(yǔ)言中經(jīng)socket接收數(shù)據(jù)的相關(guān)函數(shù)詳解,分別為recv()函數(shù)和recvfrom()函數(shù)以及recvmsg()函數(shù)的使用,需要的朋友可以參考下2015-09-09利用C++單例模式實(shí)現(xiàn)高性能配置管理器
這篇文章主要為大家詳細(xì)介紹了如何利用C++單例模式實(shí)現(xiàn)高性能配置管理器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-04-04C/C++?Linux?Socket網(wǎng)絡(luò)編程流程分析
這篇文章主要介紹了C/C++?Linux?Socket網(wǎng)絡(luò)編程,Linux環(huán)境中的C/C++?socket?與Window環(huán)境中的C/C++?socket類(lèi)似,本文所記錄的是TCP協(xié)議的socket編程,圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄功能
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06C語(yǔ)言中用于修改文件的存取時(shí)間的函數(shù)使用
這篇文章主要介紹了C語(yǔ)言中用于修改文件的存取時(shí)間的函數(shù)使用,分別為utime()函數(shù)和utimes()函數(shù)的使用,需要的朋友可以參考下2015-09-09C++中template方法undefined reference to的問(wèn)題解決
Undefined reference to 錯(cuò)誤:這類(lèi)錯(cuò)誤是在連接過(guò)程中出現(xiàn)的,本文就來(lái)介紹一下C++中template方法undefined reference to的問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03在C++中實(shí)現(xiàn)云端存儲(chǔ)變量的操作步驟
隨著云計(jì)算技術(shù)的快速發(fā)展,現(xiàn)在我們可以將數(shù)據(jù)存儲(chǔ)在云端,以便于在不同設(shè)備和地點(diǎn)訪問(wèn),在C++中,我們也可以通過(guò)一些方法來(lái)實(shí)現(xiàn)這個(gè)功能,本文將詳細(xì)介紹如何在C++中實(shí)現(xiàn)云端存儲(chǔ)變量,需要的朋友可以參考下2023-11-11