2. 構(gòu)造函數(shù) 2.1概念如果一個類中什么成員都沒有,簡稱為空類
創(chuàng)新互聯(lián)公司服務(wù)項目包括思禮網(wǎng)站建設(shè)、思禮網(wǎng)站制作、思禮網(wǎng)頁制作以及思禮網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,思禮網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到思禮省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!空類并不是說里面什么都沒有:任何類在什么都不寫時,編譯器會自動生成以下6個默認成員函數(shù)。
默認成員函數(shù):用戶沒有顯式實現(xiàn),編譯器會生成的成員函數(shù)稱為默認成員函數(shù)
class A{};
2.2 特性構(gòu)造函數(shù)是一個特殊的成員函數(shù),名字與類名相同,創(chuàng)建類類型對象時由編譯器自動調(diào)用,以保證每個數(shù)據(jù)成員都有 一個合適的初始值,并且在對象整個生命周期內(nèi)只調(diào)用一次
3. 析構(gòu)函數(shù) 3.1概念構(gòu)造函數(shù)是特殊的成員函數(shù),需要注意的是,構(gòu)造函數(shù)雖然名字叫構(gòu)造,但是構(gòu)造函數(shù)的主要任務(wù)并不是開空間創(chuàng)建對象,而是初始化對象
特點:
- 函數(shù)名與類名相同
- 無返回值
- 對象實例化時,編譯器自動調(diào)用對應(yīng)的構(gòu)造函數(shù)
- 構(gòu)造函數(shù)可以重載
class Date { public: Date() {}//無參的默認構(gòu)造 Date(int year, int mouth, int day) { _year = year; _mouth = mouth; _day = day; }//帶參數(shù)的構(gòu)造函數(shù) private: int _year; int _mouth; int _day; }; void TestDate() { Date d1; // 調(diào)用無參構(gòu)造函數(shù) Date d2(2015, 1, 1); // 調(diào)用帶參的構(gòu)造函數(shù) // 注意:如果通過無參構(gòu)造函數(shù)創(chuàng)建對象時,對象后面不用跟括號,否則就成了函數(shù)聲明 // 以下代碼的函數(shù):聲明了d3函數(shù),該函數(shù)無參,返回一個日期類型的對象 // warning C4930: “Date d3(void)”: 未調(diào)用原型函數(shù)(是否是有意用變量定義的?) Date d3();//這是聲明不是創(chuàng)建對象 }
- 如果類中沒有顯式定義構(gòu)造函數(shù),則C++編譯器會自動生成一個無參的默認構(gòu)造函數(shù),一旦用戶顯式定義編譯器將不再生成
class Date { public: //Date(int year, int mouth, int day) //{ // _year = year; // _mouth = mouth; // _day = day; //} void Print() { cout<< _year<< "-"<< _month<< "-"<< _day<< endl; } private: int _year; int _mouth; int _day; }; int main() { Date d1; // 將Date類中構(gòu)造函數(shù)屏蔽后,代碼可以通過編譯,因為編譯器生成了一個無參的默認構(gòu)造函數(shù) // 將Date類中構(gòu)造函數(shù)放開,代碼編譯失敗,因為一旦顯式定義任何構(gòu)造函數(shù),編譯器將不再生成無參構(gòu)造函數(shù),放開后報錯:error C2512: “Date”: 沒有合適的默認構(gòu)造函數(shù)可用 return 0; }
C++把類型分成內(nèi)置類型(基本類型)和自定義類型。內(nèi)置類型就是語言提供的數(shù)據(jù)類型,如:
int/char…,自定義類型就是我們使用class/struct/union等自己定義的類型 ,編譯器**生成默認的構(gòu)造函數(shù)會對自定類型成員調(diào)用的它的默認構(gòu)造函數(shù),自定義類型不處理**注意:C++11 中針對內(nèi)置類型成員不初始化的缺陷,又打了補丁,即:內(nèi)置類型成員變量在類中聲明時可以給默認值(也就是缺省值)
無參的構(gòu)造函數(shù)和全缺省的構(gòu)造函數(shù)都稱為默認構(gòu)造函數(shù),并且默認構(gòu)造函數(shù)只能有一個。注意:無參構(gòu)造函數(shù)、全缺省構(gòu)造函數(shù)、我們沒寫編譯器默認生成的構(gòu)造函數(shù),都可以認為是默認構(gòu)造函數(shù)。
3.2 特性析構(gòu)函數(shù):與構(gòu)造函數(shù)功能恰巧相反,析構(gòu)函數(shù)不是完成對對象本身的銷毀,局部對象銷毀工作是由編譯器完成的。而對象在銷毀時會自動調(diào)用析構(gòu)函數(shù),完成對象中資源的清理工作
4.拷貝構(gòu)造函數(shù) 4.1 概念構(gòu)造函數(shù)是特殊的成員函數(shù),其特征如下:
析構(gòu)函數(shù)是在類名前面加上字符~
無參數(shù)無返回值類型
一個類只能有一個析構(gòu)函數(shù),若未顯式定義,系統(tǒng)會自動生成默認的析構(gòu)函數(shù),注意:析構(gòu)函數(shù)不能重載
對象生命周期結(jié)束時,C++編譯器自動調(diào)用析構(gòu)函數(shù)
關(guān)于編譯器自動生成的析構(gòu)函數(shù),是否會完成一些事情呢?下面的程序我們會看到,編譯器生成的默認析構(gòu)函數(shù),對自定類型成員調(diào)用它的析構(gòu)函數(shù)。
如果==類中沒有申請資源時,析構(gòu)函數(shù)可以不寫(它是回收資源的)==,直接使用編譯器生成的默認析構(gòu)函數(shù),比如Date類;有資源申請時,一定要寫,否則會造成資源泄漏,比如Stack類
4.2 特征拷貝構(gòu)造函數(shù):只有單個形參,該形參是對本類類型對象的引用(一般常用const修飾),在用已存在的類類型對象創(chuàng)建新對象時由編譯器自動調(diào)用。
5.賦值運算符重載 5.1 運算符重載
拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個重載形式
拷貝構(gòu)造函數(shù)的**參數(shù)只有一個且必須是類類型對象的引用,使用傳值方式編譯器直接報錯,**因為會引發(fā)無窮遞歸調(diào)用。(因為形參傳遞給函數(shù)是拷貝構(gòu)造,寫拷貝構(gòu)造去調(diào)用拷貝構(gòu)造就會引起無窮遞歸
class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } // Date(const Date& d) // 正確寫法 Date(const Date d) // 錯誤寫法:編譯報錯,會引發(fā)無窮遞歸 { _year = d._year; _month = d._month; _day = d._day; } private: int _year; int _month; int _day; };
.**若未顯示定義,編譯器會生成默認的拷貝構(gòu)造。**默認的拷貝構(gòu)造函數(shù)對象會按內(nèi)存存儲按字節(jié)序完成拷貝,這種拷貝叫做淺拷貝,或者值拷貝
注意:在編譯器生成的默認拷貝構(gòu)造函數(shù)中,內(nèi)置類型是按照字節(jié)方式直接拷貝的,而**自定義類型是調(diào)用其拷貝構(gòu)造函數(shù)完成拷貝的 **
編譯器生成的默認拷貝構(gòu)造函數(shù)已經(jīng)可以完成字節(jié)序的值拷貝了, 還需要自己顯式實現(xiàn)嗎?當然
注意:類中如果沒有涉及資源申請時,拷貝構(gòu)造函數(shù)是否寫都可以;一旦涉及到資源申請時,則拷貝構(gòu)造函數(shù)是一定要寫的,否則就是淺拷貝。 就會出現(xiàn)倆個類指向同一塊資源,調(diào)用析構(gòu)函數(shù)的時候,析構(gòu)函數(shù)可以能就會析構(gòu)兩次,引發(fā)問題
拷貝構(gòu)造調(diào)用場景:
- 使用已存在對象創(chuàng)建新對象
- 函數(shù)參數(shù)類型為類類型對象
- 函數(shù)返回值類型為類類型對象
為了提高程序效率,一般對象傳參時,盡量使用引用類型,返回時根據(jù)實際場景,能用引用盡量使用引用。
5.2 賦值運算符重載C++為了增強代碼的可讀性引入了運算符重載,運算符重載是具有特殊函數(shù)名的函數(shù),也具有其返回值類型,函數(shù)名字以及參數(shù)列表,其返回值類型與參數(shù)列表與普通的函數(shù)類似。
函數(shù)名字為:關(guān)鍵字operator后面接需要重載的運算符符號。
函數(shù)原型:**返回值類型 operator操作符(參數(shù)列表) **注意:
- 不能通過連接其他符號來創(chuàng)建新的操作符:比如operator@
- 重載操作符必須有一個類類型參數(shù)
- 用于內(nèi)置類型的運算符,其含義不能改變,例如:內(nèi)置的整型+,不 能改變其含義
- 作為類成員函數(shù)重載時,其形參看起來比操作數(shù)數(shù)目少1,因為成員函數(shù)的第一個參數(shù)為隱藏的this
.* :: sizeof ?: .
注意以上5個運算符不能重載。
- 賦值運算符重載格式
- 參數(shù)類型:const T&,傳遞引用可以提高傳參效率
- 返回值類型:T&,返回引用可以提高返回的效率,有返回值目的是為了支持連續(xù)賦值
- 檢測是否自己給自己賦值
- 返回*this :要復(fù)合連續(xù)賦值的含義
- 賦值運算符只能重載成類的成員函數(shù)不能重載成全局函數(shù)
原因:賦值運算符如果不顯式實現(xiàn),編譯器會生成一個默認的。此時用戶再在類外自己實現(xiàn)一個全局的賦值運算符重載,就和編譯器在類中生成的默認賦值運算符重載沖突了,故賦值運算符重載只能是類的成員函數(shù)。
5.3 前置++和后置++重載
用戶沒有顯式實現(xiàn)時,編譯器會生成一個默認賦值運算符重載,以值的方式逐字節(jié)拷貝。注意:內(nèi)置類型成員變量是直接賦值的,而自定義類型成員變量需要調(diào)用對應(yīng)類的賦值運算符重載完成賦值。 (和拷貝構(gòu)造一個意思,如果有資源的申請就必須要實現(xiàn)深拷貝,不然會出問題)
如果類中未涉及到資源管理,賦值運算符是否實現(xiàn)都可以;一旦涉及到資源管理則必須要實現(xiàn)
7.const成員class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } // 前置++:返回+1之后的結(jié)果 // 注意:this指向的對象函數(shù)結(jié)束后不會銷毀,故以引用方式返回提高效率 Date& operator++() { _day += 1; return *this; } // 后置++: // 前置++和后置++都是一元運算符,為了讓前置++與后置++形成能正確重載 // C++規(guī)定:后置++重載時多增加一個int類型的參數(shù),但調(diào)用函數(shù)時該參數(shù)不用傳遞,編譯器自動傳遞 // 注意:后置++是先使用后+1,因此需要返回+1之前的舊值,故需在實現(xiàn)時需要先將this保存一份,然后給this + 1 // 而temp是臨時對象,因此只能以值的方式返回,不能返回引用 Date operator++(int) { Date temp(*this); _day += 1; return temp; } void print() { cout<< _year<< " "<< _month<< " "<< _day<< endl; } private: int _year; int _month; int _day; }; int main() { Date d; Date d1(2022, 1, 13); d = d1++; // d: 2022,1,13 d1:2022,1,14 d.print(); d1.print(); d = ++d1; // d: 2022,1,15 d1:2022,1,15 d.print(); d1.print(); return 0; }
8.取地址及const取地址操作符重載將const修飾的“成員函數(shù)”稱之為const成員函數(shù),const修飾類成員函數(shù),實際修飾該成員函數(shù)隱含的this指針,表明在該成員函數(shù)中不能對類的任何成員進行修改
class Date { public : Date* operator&() { return this ; } const Date* operator&()const { return this ; } private : int _year ; // 年 int _month ; // 月 int _day ; // 日 };
這兩個運算符一般不需要重載,使用編譯器生成的默認取地址的重載即可,只有特殊情況,才需要重載,比如想讓別人獲取到指定的內(nèi)容
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
分享題目:類和對象中-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://muchs.cn/article30/ceecso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機網(wǎng)站建設(shè)、電子商務(wù)、響應(yīng)式網(wǎng)站、網(wǎng)站維護、網(wǎng)站改版、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容