您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“怎么掌握C++類(lèi)與對(duì)象”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
C++為了增強(qiáng)代碼的可讀性引入了運(yùn)算符重載,運(yùn)算符重載是具有特殊函數(shù)名的函數(shù),也具有其返回值類(lèi)型,函數(shù)名字以及參數(shù)列表,其返回值類(lèi)型與參數(shù)列表與普通的函數(shù)類(lèi)似。
其函數(shù)名為: operator + 需要重載的運(yùn)算符符號(hào)(參數(shù)列表)。
需要注意的是:
(1)不能通過(guò)連接其他符號(hào)來(lái)創(chuàng)建新的操作符,比如operator$.也就是說(shuō),operator只能重載已有的操作符,其他的符號(hào)不能通過(guò)該函數(shù)來(lái)創(chuàng)造。
(2)重載操作符必須有一個(gè)類(lèi)類(lèi)型或枚舉類(lèi)型的操作數(shù)。
(3)用于內(nèi)置類(lèi)型的操作符,其含義不能改變。比如,內(nèi)置整型的==,不能改變其類(lèi)型。
(4)運(yùn)算符重載函數(shù)的參數(shù)個(gè)數(shù)為操作符的操作數(shù)個(gè)數(shù),比如對(duì)于==操作符,其操作數(shù)由兩個(gè),那么重載該操作符的函數(shù)參數(shù)應(yīng)為2個(gè),即operator==(int x,int y);
(5)對(duì)于作為類(lèi)成員的操作符重載函數(shù),其參數(shù)看起來(lái)要比操作符的操作數(shù)個(gè)數(shù)少一個(gè),這是因?yàn)楹瘮?shù)隱含了一個(gè)形參this,并且this指針被限定為第一個(gè)形參。
(6)語(yǔ)法規(guī)定,有五個(gè)操作符不能被重載,即.*(成員中指針解引用)、::(作用域限定符)、?:(三目操作符)、.(成員(對(duì)象)選擇)、sizeof(長(zhǎng)度運(yùn)算符)。這里需要注意的是.(解引用操作符)可以被重載,不能被重載的操作符為s1.*ptr中的.*操作符,即訪問(wèn)類(lèi)中指針成員并解引用。
用我們熟悉的日期類(lèi)來(lái)舉例,比如我們要實(shí)現(xiàn)==這個(gè)操作符的重載函數(shù):
//頭文件Date.h中 class Date { public: //獲取某年某月的天數(shù) int GetDay(int year, int month) { assert(month > 0 && month < 13); int Day[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; if (month == 2 && year % 4 == 0 && year % 100 != 0 || year % 400 == 0)//閏年二月 { return 29; } return Day[month]; } //全缺省的構(gòu)造函數(shù) Date(int year = 0, int month = 1, int day = 1) { _year = year; _month = month; _day = day; //判斷初始化的日期是否合理 if (_month >= 13 || _day > GetDay(_year, _month) || _month <= 0 || _day <= 0 || _year < 0) { cout << _year << "/" << _month << "/" << _day << "->"; cout << "非法日期" << endl; } } void Print() { cout << _year << "/" << _month << "/" << _day << endl; } //拷貝構(gòu)造函數(shù),d1(d2) Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } //==運(yùn)算符重載 bool operator==(const Date& d) const; private: int _year; int _month; int _day; }; //源文件Date.cpp中 //需要注意,左操作數(shù)為this指針指向的調(diào)用函數(shù)的對(duì)象, //即函數(shù)等價(jià)于bool operator==(Date* this, const Date d); bool Date::operator==(const Date& d) const { return this->_year == d._year && this->_month == d._month && this->_day == d._day; }
由于==操作符的結(jié)果為真或假,因此函數(shù)的返回值設(shè)為bool類(lèi)型。
我們知道賦值運(yùn)算符為=,那么重載賦值運(yùn)算符的函數(shù)應(yīng)為:
//Date.cpp中 Date& Date::operator=(const Date& d) { if (this != &d)//排除兩個(gè)操作數(shù)相同的情況 { _year = d._year; _month = d._month; _day = d._day; } return *this; }
需要注意的是:
(1)首先,為了減少形參拷貝導(dǎo)致的開(kāi)銷(xiāo),我們用引用作為形參類(lèi)型;其次,由于函數(shù)并不會(huì)修改原操作數(shù),因此加上const可以保證代碼的安全性。
(2)這里的*this即this所指向的對(duì)象出了這個(gè)賦值重載函數(shù)并不會(huì)銷(xiāo)毀,因此可以用引用返回,返回類(lèi)型為類(lèi)名加引用。
(3)如果操作數(shù)為兩個(gè)相同的對(duì)象,回導(dǎo)致賦值操作多余,因此需要檢查是否出現(xiàn)自己給自己賦值的情況。
一個(gè)類(lèi)如果沒(méi)有顯式定義賦值運(yùn)算符重載,編譯器也會(huì)生成一個(gè),完成對(duì)象按字節(jié)序的淺拷貝(值拷貝)。
以上面的Date類(lèi)為例,在我們不實(shí)現(xiàn)賦值操作符重載函數(shù)的情況下:
int main() { Date d1(2021,10,15); Date d2; //這里d2回調(diào)用編譯器自己生成的operator=函數(shù)完成拷貝 //即d2.operator=(d1); d2 = d1; return 0; }
和拷貝構(gòu)造函數(shù)一樣,編譯器生成的默認(rèn)賦值重載函數(shù)已經(jīng)可以完成字節(jié)序的值拷貝了,對(duì)于Date類(lèi)這樣的我們無(wú)需自己定義,但是對(duì)于Stack這樣會(huì)向內(nèi)存申請(qǐng)空間的類(lèi),不能直接調(diào)用編譯器的默認(rèn)函數(shù),會(huì)對(duì)已經(jīng)釋放的空間重復(fù)釋放。
賦值重載函數(shù)與拷貝構(gòu)造函數(shù)的作用都是實(shí)現(xiàn)字節(jié)序的拷貝,那么二者之間有什么區(qū)別呢?
首先,拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個(gè)函數(shù)重載形式,其函數(shù)名為類(lèi)名,無(wú)返回值,而賦值重載函數(shù)為=這個(gè)操作符的重載,其函數(shù)名為operator=,返回值為類(lèi)名,需要注意的是函數(shù)重載與操作符重載二者之間沒(méi)有任何關(guān)聯(lián)。
其次,一個(gè)對(duì)象在初始化時(shí)調(diào)用的時(shí)拷貝構(gòu)造函數(shù),而對(duì)象初始化完成后再調(diào)用即為賦值重載函數(shù),比如:
int main() { Date d1(2021,10,15); //調(diào)用拷貝構(gòu)造函數(shù),相對(duì)于Date d2(d1); Date d2 = d1; Date d3(2021,10,15); Date d4; //調(diào)用賦值重載函數(shù),即d4.operator=(d3); d4 = d3; return 0; }
最后,由于=可以連續(xù)使用,因此賦值重載函數(shù)可以連續(xù)調(diào)用,比如:
int main() { Date d1(2021,10,15); Date d2; Date d3; //連續(xù)調(diào)用,相當(dāng)于,d3 = (d2 = d1); 而d2 = d1有一個(gè)返回值 //該返回值再作為操作數(shù)賦值給d3 //也就相當(dāng)于d3.operator(d2.operator(d1)); d3 = d2 = d1; return 0; }
學(xué)習(xí)完操作符重載,我們可以實(shí)現(xiàn)操作符==、+=、-=、>、<等等。
//賦值運(yùn)算符重載,d2=d3 -> d2.operater=(d3) Date& operator=(const Date& d);//由于在類(lèi)域中this所指向的對(duì)象并不會(huì)銷(xiāo)毀,因此可以用引用返回 //日期+=天數(shù) Date& operator+=(int day); //日期+天數(shù) Date operator+(int day) const; //日期-=天數(shù) Date& operator-=(int day); //日期-天數(shù) Date operator-(int day) const; //前置++ Date& operator++(); //后置++ Date operator++(int); //前置-- Date& operator--(); //后置-- Date operator--(int); //==運(yùn)算符重載 bool operator==(const Date& d) const; //!=運(yùn)算符重載 inline bool operator!=(const Date& d) const; //>運(yùn)算符重載 bool operator>(const Date& d); //<運(yùn)算符重載 inline bool operator<(const Date& d); //>=運(yùn)算符重載 inline bool operator>=(const Date& d); //<=運(yùn)算符重載 inline bool operator<=(const Date& d); //日期 - 日期,返回天數(shù) int operator-(const Date& d) const;
我們先來(lái)看看下面這個(gè)代碼:
//>運(yùn)算符重載 bool operator>(const Date& d); void Test6() { const Date d1(2021, 10, 16); Date d2 = d1 + 100; cout << (d1 > d2) << endl; }
實(shí)際運(yùn)行過(guò)程中會(huì)發(fā)現(xiàn)d1 > d2
這句代碼編譯不過(guò)去,這是因?yàn)殡[含的this指針默認(rèn)的類(lèi)型為不加const修飾的指針類(lèi)型,而d1的類(lèi)型為const修飾的變量,因此傳參給this后放大了修改的權(quán)限,導(dǎo)致出現(xiàn)錯(cuò)誤。但是this指針的類(lèi)型我們是無(wú)法修改的,那么要怎么解決這種情況呢?這就需要用到我們接下來(lái)要介紹的const修飾類(lèi)的成員函數(shù)了。
將const修飾的類(lèi)成員函數(shù)稱(chēng)之為const成員函數(shù),const修飾類(lèi)成員函數(shù),實(shí)際修飾該成員函數(shù)隱含的this指針,表明在該成員函數(shù)中不能對(duì)類(lèi)的任何成員進(jìn)行修改。
比如說(shuō)上述代碼我們可以修改為:
//>運(yùn)算符重載,其相當(dāng)于bool operator>(const Date* this, const Date& d); bool operator>(const Date& d) const;
1.成員函數(shù)加const,變成const成員函數(shù),這樣既可以讓const對(duì)象調(diào)用,也可以讓非const對(duì)象調(diào)用。
2.不是所有的成員函數(shù)都要加const,因?yàn)橛械暮瘮?shù)需要用this指針修改成員變量。
3.一個(gè)成員函數(shù)是否要加const應(yīng)看其功能,若為修改型,比如operator+=();Push();等不需要加const;而對(duì)于只讀型,Print();operator+();等就最好加上const。
綜上,如果要修改成員就不加const,若不修改則最好加上const。
類(lèi)的最后兩個(gè)默認(rèn)成員函數(shù)為操作符&的重載及其加上const修飾的函數(shù)。
class Date { public : Date* operator&() { return this ; } const Date* operator&()const { return this ; } private : int _year ; // 年 int _month ; // 月 int _day ; // 日 };
這兩個(gè)運(yùn)算符一般不需要重載,使用編譯器生成的默認(rèn)取地址的重載即可,只有特殊情況,才需要重載,比如想讓別人獲取到指定的內(nèi)容!但在實(shí)際過(guò)程中應(yīng)用不多。
“怎么掌握C++類(lèi)與對(duì)象”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。