目錄
一、拷貝構(gòu)造函數(shù)
1.1 什么是拷貝構(gòu)造函數(shù)?
1.2 為什么得是引用?
1.3 使用拷貝構(gòu)造函數(shù)
1.4 拷貝構(gòu)造函數(shù)有什么用?
二、運(yùn)算符重載
2.1 什么是運(yùn)算符重載?
2.2? 嘗試前須知
2.3 常見(jiàn)運(yùn)算符重載
2.3.1+=運(yùn)算符重載
2.3.2+運(yùn)算符重載
2.3.3前置++和后置++運(yùn)算符重載
三、下期預(yù)告
前言:C++初階系列,每一期博主都會(huì)使用簡(jiǎn)單樸素的語(yǔ)言將對(duì)應(yīng)的知識(shí)分享給大家,爭(zhēng)取讓所有人都可以聽(tīng)懂,C++初階系列會(huì)持續(xù)更新,上學(xué)期間將不定時(shí)更新,但總會(huì)更的
一、拷貝構(gòu)造函數(shù)
1.1 什么是拷貝構(gòu)造函數(shù)?
拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的重構(gòu),也就是說(shuō)它也沒(méi)有需要返回的東西,同樣是為了構(gòu)造成員而生。
拷貝構(gòu)造函數(shù)只有單個(gè)形參,該形參是對(duì)本類類型對(duì)象的引用(一般常用const修飾),在用已存在的類類型對(duì)象創(chuàng)建新對(duì)象時(shí)由編譯器自動(dòng)調(diào)用。
1.2 為什么得是引用?
為什么這個(gè)形參得是被類對(duì)象的引用呢,我直接傳遞我這個(gè)要拷貝的目標(biāo)不可以嗎,不是一樣的操作嗎。有如下代碼就完美的符合你的想法
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1,int month=1,int day=1)
{
_year = year;
_month = month;
_day = day;
}
Date(Date date)
{
_year = date._year;
_month = date._month;
_day = date._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
}
現(xiàn)在的編譯器很智能,直接就阻止了你的無(wú)窮遞歸行為,為什么會(huì)發(fā)生無(wú)窮遞歸呢。
這樣說(shuō)吧,假設(shè)你有一個(gè)Date d和你個(gè)test函數(shù),你想將d傳遞給test函數(shù),于是編譯器就會(huì)調(diào)用這個(gè)拷貝構(gòu)造函數(shù),而調(diào)用這個(gè)拷貝構(gòu)造函數(shù)的時(shí)候你會(huì)生成一個(gè)叫做date的形參,而這個(gè)形參剛好也是Date類型的變量,那么它也會(huì)走向這個(gè)拷貝構(gòu)造函數(shù),于是拷貝構(gòu)造函數(shù)調(diào)用拷貝構(gòu)造函數(shù),再調(diào)用拷貝構(gòu)造函數(shù).......
1.3 使用拷貝構(gòu)造函數(shù)
簡(jiǎn)單的拷貝并打印一下,代碼什么的自己去敲一遍效果好一些,別光看,至于為什么要加const是因?yàn)槲覀儌鬟f過(guò)去的變量是被拷貝的,是不會(huì)被修改的? ?加個(gè)const是為了避免一些低級(jí)錯(cuò)誤的發(fā)生,比方說(shuō)修改到了被拷貝的對(duì)象,同時(shí)增加了代碼的可讀性。
1.4 拷貝構(gòu)造函數(shù)有什么用?
學(xué)到這里,大家恐怕也是明白了,拷貝構(gòu)造函數(shù)就是簡(jiǎn)單地將目標(biāo)內(nèi)容拷貝給新定義的對(duì)象罷了, 那么它有用嗎,這是很多初學(xué)者的疑惑,實(shí)際上它不僅僅是有用,它是很有用。
比方說(shuō),我們現(xiàn)在實(shí)現(xiàn)的日期類的拷貝構(gòu)造函數(shù),其實(shí)只是涉及到了一個(gè)簡(jiǎn)單的值拷貝,而到后期我們使用什么棧啊,堆啊,二叉樹(shù)之類的東西,我們?nèi)绻€是簡(jiǎn)單地進(jìn)行值拷貝,我們拷貝的東西不就只有一具空殼嗎,我們得采取一些方式實(shí)現(xiàn)深拷貝,也就是把棧里面的值都給拷貝出來(lái)的那種拷貝,如此才可以保證這兩個(gè)東西一模一樣,才能夠達(dá)到預(yù)期的效果。
二、運(yùn)算符重載
2.1 什么是運(yùn)算符重載?
其實(shí)很多小伙伴應(yīng)該在使用C語(yǔ)言的時(shí)候就有過(guò)這樣的苦惱,我這結(jié)構(gòu)體+結(jié)構(gòu)體沒(méi)法玩啊,我得用.或->獲取結(jié)構(gòu)體成員才能夠?qū)锩娴某蓡T進(jìn)行操作啊,太費(fèi)勁了,就是寫(xiě)了個(gè)函數(shù),還得來(lái)個(gè)d3=addition(d1,d2);就不能d1+d2嗎? ??在C++中,是可以實(shí)現(xiàn)的,這個(gè)操作就叫做運(yùn)算符重載,也就是對(duì)運(yùn)算符進(jìn)行補(bǔ)充定義。
2.2? 嘗試前須知
operator用在運(yùn)算符重載上,比方說(shuō)+運(yùn)算符的重載,在進(jìn)行重載部分的書(shū)寫(xiě)時(shí),我們就得在之前加上operator,大概可以用這個(gè)公式闡述:返回類型+operator+重載的運(yùn)算符(參數(shù))
運(yùn)算符重載既可以寫(xiě)在類的里面,也可以寫(xiě)在類的外面? ? 而寫(xiě)在類的外面我們往往會(huì)用到一個(gè)操作叫友元,這個(gè)操作的大致意思就是令你這個(gè)在類外面的東西成為我這個(gè)類的朋友,因此你這個(gè)類外面的東西就可以訪問(wèn)到類中private中的內(nèi)容,對(duì)于友元這里不再贅述,之后會(huì)進(jìn)行講解。
有的小伙伴又會(huì)有些問(wèn)題,那么我們直接把private去掉,或者不在private中定義成員變量。我想說(shuō)的是,這樣多少有點(diǎn)舍本逐末了,因?yàn)樵贑++中之所以會(huì)有類的原因,有一部分就是因?yàn)槎鄠€(gè)結(jié)構(gòu)體的函數(shù)和變量過(guò)于混亂,而按你的方法去做,那么這個(gè)類的成員變量所有人都可以進(jìn)行操作,那哪還有什么規(guī)矩,這個(gè)類的創(chuàng)建又有什么意義?
因此,博主在進(jìn)行運(yùn)算符重載的時(shí)候使用的方法是在類中進(jìn)行運(yùn)算符重載,這樣既可以訪問(wèn)到私有的成員變量,還可以保證代碼的嚴(yán)謹(jǐn)性。
注意:
1.不能通過(guò)連接其他符號(hào)來(lái)創(chuàng)建新的操作符:比如operator@?
2.重載操作符必須有一個(gè)類類型參數(shù)
3.用于內(nèi)置類型的運(yùn)算符,其含義不能改變,例如:內(nèi)置的整型+,不 能改變其含義
4.作為類成員函數(shù)重載時(shí),其形參看起來(lái)比操作數(shù)數(shù)目少1,因?yàn)槌蓡T函數(shù)的第一個(gè)參數(shù)為隱
藏的this
5. .*? ?::? ? sizeof? ? ?:? ? . 注意以上5個(gè)運(yùn)算符不能重載。這個(gè)經(jīng)常在筆試選擇題中出現(xiàn)。這5個(gè)死記硬背記住就ok了。
2.3 常見(jiàn)運(yùn)算符重載
2.3.1+=運(yùn)算符重載
目標(biāo):實(shí)現(xiàn)一個(gè)日期+天數(shù),日期被修改為過(guò)了多少天的日期
很多人第一次寫(xiě)會(huì)寫(xiě)成這樣,而編譯器報(bào)錯(cuò)是因?yàn)?strong>多了一個(gè)this指針過(guò)去,已經(jīng)達(dá)到了三目運(yùn)算符的操作了? ?因此我們只需要把Date d1去掉即可,但因?yàn)橛衪his指針的存在,我們一樣能對(duì)這個(gè)變量進(jìn)行操作。
實(shí)現(xiàn)這個(gè)之前我們可以寫(xiě)一個(gè)GetMonthDay函數(shù)來(lái)獲得沒(méi)一月份的天數(shù),值得注意的一點(diǎn)是閏年時(shí)2月為29日,接著我們來(lái)講講實(shí)現(xiàn)思路,我們的返回值最好設(shè)置成Date&型的,因?yàn)?=操作的目標(biāo)出了函數(shù)作用域在main中依然存在,因此使用Date&類型的返回值可以令編譯器的效率得到提高。
可以先在目標(biāo)的_day上加上day,這樣能方便之后的進(jìn)位,比方說(shuō)2023-11-16?+100就先處理成2023-11-116,之后通過(guò)GetMonthDay取得的具體進(jìn)位數(shù)據(jù)來(lái)進(jìn)行進(jìn)位即可,這里就可以通過(guò)循環(huán)實(shí)現(xiàn),當(dāng)_day>GetMonthDay時(shí)意味著需要進(jìn)位,因此可以以這個(gè)來(lái)作為循環(huán)是否繼續(xù)的條件,之后的實(shí)現(xiàn)便只需要注意一些細(xì)節(jié)即可,比方說(shuō),月滿12進(jìn)1之類的。
int GetMonthDay(int year, int month)
{
int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
//之所以是13是為了更加符合日期的返回,一月就返回?cái)?shù)組下標(biāo)為1的值
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
{
return 29;
}
return arr[month];
}
Date& operator +=(int day)
{
_day += day;
while (_day > GetMonthDay(_year,_month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month>12)
{
_month = 1;
_year++;
}
}
return *this;
}
測(cè)試:
2.3.2+運(yùn)算符重載
有了+=運(yùn)算符之后+運(yùn)算符就很好操作了,復(fù)用一下就好?
使用臨時(shí)變量的原因是因?yàn)椋?運(yùn)算符并不改變?cè)瓉?lái)變量的值,比方說(shuō)a=b+100;這里的b也不會(huì)被修改
Date operator+(int day)
{
Date tmp = *this;
tmp += day;
return tmp;
}
2.3.3前置++和后置++運(yùn)算符重載
在C++中前置++和后置++如果我們要對(duì)它進(jìn)行重載,你就會(huì)驚訝的發(fā)現(xiàn),它們兩的運(yùn)算符名字其實(shí)是一模一樣的,這怎么進(jìn)行區(qū)分呢,祖師爺其實(shí)也沒(méi)有太好的辦法,他對(duì)這個(gè)地方做了特殊化處理,就像我們做oj題時(shí)遇到的特殊情況,單獨(dú)處理一樣。祖師爺也是這么做的,他規(guī)定前置++和后置++的區(qū)別就在于,后置++的參數(shù)有個(gè)int型的
什么意思?差不多是這樣,operator++(),operator++(int)前面的就代表著前置++,后面的那個(gè)就代表著后置++,那為什么是int,不能是float嗎。我只能這么說(shuō),這是巧合,祖師爺就想拿int來(lái)區(qū)分,僅此而已。
有了+和+=實(shí)現(xiàn)起來(lái)就直接復(fù)用就好了
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-754472.html
三、下期預(yù)告
大概在明天,博主會(huì)來(lái)一篇日期類實(shí)現(xiàn)詳解,那里面會(huì)講到友元操作,期待你的到來(lái)QAQ?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-754472.html
到了這里,關(guān)于C++初階 類和對(duì)象(下)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!