国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II

這篇具有很好參考價值的文章主要介紹了【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II

Halo,這里是Ppeua。平時主要更新C語言,C++,數(shù)據(jù)結(jié)構(gòu)算法…感興趣就關(guān)注我吧!你定不會失望。


【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II

0.運算符重載

C++中為了增強代碼的可讀性,加入了運算符的重載,與其他函數(shù)重載一樣。其命名格式如下:

返回值類型 operator操作符(參數(shù)列表)

Date operator<(Date&d1)

但并不是所有運算符都可以重載的:

  1. 不可以自定義出一個全新的操作符,如@
  2. .* :: sizeof ?: . 以上操作符不能重載,特別是第一個.*

接下來我們定義一個日期類來作為操作符重載的實踐:

class Date{
public:
    Date(int day=1,int month=1,int year=1)
    {
        if(month>0&&month<13&&day>0&&day<getmonth(year,month))
            _day=day,_month=month,_year=year;
        else
            cout<<"輸入錯誤";
    }

    Date(const Date&d)
    {
        _day=d._day;
        _month=d._month;
        _year=d._year;
        cout<<"copy";
    }
private:
    int _year;
    int _month;
    int _day;
}

這是一個最基本的類函數(shù),其包括一個默認構(gòu)造函數(shù),以及一個拷貝構(gòu)造函數(shù),拷貝構(gòu)造函數(shù)會在調(diào)用時輸出:“copy”,這將有助于我們后期分析函數(shù).

1.賦值運算符 = 重載

先來看看他是怎么定義的吧.同樣符合上方的定義法則:

 Date& operator=(const Date&d)
    {
        _day=d._day;
        _month=d._month;
        _year=d._year;
        return *this;
    }

為什么需要返回值調(diào)用呢?因為這樣做可以節(jié)省空間。以引用的方式傳參、返回值不需要調(diào)用拷貝構(gòu)造函數(shù)

那this不是形式參數(shù)嘛?為什么出作用域還能被引用呢?*this本身是形式參數(shù),但是 this指向的是date對象,其棧幀存儲在Main函數(shù)中,所以this會被銷毀,而返回的是this指向的對象,并不會被銷毀

加入const只是一個保險,讓我們不會改變傳入的參數(shù)

我們可以以一段代碼來演示一下:

class Date{
    
public:
    
   
    Date(int day=1,int month=1,int year=1)
    {
        if(month>0&&month<13&&day>0&&day<getmonth(year,month))
            _day=day,_month=month,_year=year;
        else
            cout<<"輸入錯誤";
    }

    Date(const Date &d)
    {
        _day=d._day;
        _month=d._month;
        _year=d._year;
        cout<<"copy";
    }

    Date& operator=(const Date &d)
    {
        _day=d._day;
        _month=d._month;
        _year=d._year;
        return *this;
    }
int main()
{ 
    Date d1(2,5,2024);
    Date d2;
    d2=d1;
}

先將兩個引用都去掉,運行會發(fā)現(xiàn),調(diào)用了兩次拷貝構(gòu)造,分別為傳值以及返回值

【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II

**加上后則不會調(diào)用拷貝構(gòu)造,所以這樣寫節(jié)省空間與時間。**在編譯階段,改代碼會被轉(zhuǎn)變成

d2.operator=(d1)

這也方便我們對這個操作符的具體執(zhí)行方式進行理解。

至于為什么需要返回Date類型呢?考慮以下場景:

int a;
int b;
int c;
a=b=c=1;

這段代碼運行的實質(zhì)為:
【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II

所以我們需要令其返回Date類型來滿足這種情況:

int main()
{
     
    Date d1(2,5,2024);
    Date d2;
    Date d3;
    d3=d2=d1;
}

賦值運算符如果不自己定義,系統(tǒng)就會自動生成一個賦值運算符(這與之前提到的構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、析構(gòu)函數(shù)),其調(diào)用規(guī)則業(yè)余之前一樣,若沒有定義則內(nèi)置類型完成淺拷貝,自定義類型調(diào)用其自定義的賦值運算符重載,所以與調(diào)用拷貝構(gòu)造函數(shù)相同,涉及空間管理的內(nèi)置類型,我們需要自己定義拷貝構(gòu)造函數(shù)。這也導致賦值運算符不能定義在全局,只能定義在類中,若在自己在全局定義一個就會和類中定義的沖突。

2.比較運算符 == 重載

bool operator==(const Date&d)const
    {
        if(_year==d._year&&_month==d._month&&_day==d._day)
        {
            return true;
        }
        return false;
    }

三個都相同則返回true,否則返回false,這整體邏輯很好理解。這個函數(shù)并不是默認函數(shù),所以我們可以把它定義在全局,也可以把他定義在類中。

若定義在全局會出現(xiàn)類中私有成員無法訪問的問題(這之后會解決,但現(xiàn)在我們?yōu)榱艘?guī)避這個問題我們先將其放在類中)

那這個const為什么放在外面呢?這里是對this指針,也就是本體的一個修飾,因為this指針是隱式的存在,且在這個重載中我們并不會改變本體,所以對其加上修飾

this指針原來的模樣:無法改變this指針指向的內(nèi)容,但可以改變其值

Date * const this

現(xiàn)在修飾后:既無法改變this指針指向的內(nèi)容,也無法改變其值,對其起到了一個保護的作用

const Date * const this 

3.比較運算符 != 重載

 bool operator!=(const Date&d)const
    {
        if(*this==d)return false;
        return true;
    }

這里直接復用了上方的結(jié)果,也證明了重載運算符的強大之處hhhh

4.比較運算符 < 重載

 bool operator<(const Date &d)const
    {
        if(_year<d._year)
        {
            return true;
        }
        if(_year==d._year&&_month<d._month)
        {
            return true;
        }
        if(_year==d._year&&_month==d._month&&_day<d._day)
        {
            return true;
        }
        return false;  
    }

主要為邏輯的實現(xiàn):

  1. 若年小,則直接返回true
  2. 若年相同,月小,直接返回true
  3. 若年月都相同,天數(shù)小,直接返回true

若不滿足以上情況,則說明不小于,則直接返回false

5.比較運算符 <= 重載

 bool operator<=(const Date &d)const
    {
        return *this<d||*this==d;
    }

也是對之前寫過的==以及<的一個復用.若小于或者等于則滿足小于等于

6. 比較運算符 > 重載

bool operator>(const Date &d)const
{
     return (!(*this<d)&&(*this!=d))?true:false;
}

若不小于且不等于則滿足小于等于

7.比較運算符 >= 重載

bool operator>=(const Date &d)const
    {
        return !(*this<d);
    }

若不小于則滿足大于等于

8. 賦值運算符 += 與 + 重載

在實現(xiàn)接下來的重載中,為了方便獲得每一個月份的具體日期,包括閏年平年的判斷。在類中實現(xiàn)了一個getmonth函數(shù)用來返回每一個月具體天數(shù)。

int getmonth(int year,int month)
    {
        static int monthday[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
        if((year%4==0&&year%100!=0)||year%400==0)
        {
            if(month==2)return 29;
        }
        return monthday[month];
    }

傳入年與月,進行判斷具體日期數(shù),其中閏年滿足四年一閏,百年不閏,四百年一閏

接下來進行+=的實現(xiàn):這里需要先判斷下若Day<0,則等價于計算*this-=Day

Date& operator+=(int Day)
    {
    	if(Day<0)
        {
            *this-=(-Day);
            return *this;
        }
        _day+=Day;
        while(_day>getmonth(_year,_month))
        {
            _day-=getmonth(_year,_month);
            ++_month;
            if(_month>12)
            {
                _month=1;
                _year++;
            }
        }
        return *this;
    }

具體實現(xiàn)邏輯如下:
【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II

那么我們來看看+的邏輯:

Date operator+(int day)
    {
        Date tmp=*this;
        tmp+=day;
        tmp.print();
        return tmp;
    }

為了不改變Date對象的本身,需要先將Date復制一份(這里使用拷貝構(gòu)造函數(shù),而不是賦值運算符重載,因為其在初始化對象時賦值),然后復用+=,最后返回其本身.因為是局部參數(shù),所以并不能返回引用,因為tmp出作用域會被銷毀.

9.賦值運算符 -= 與 - 重載:

-=:

 Date& operator-=(const int Day)
    {
        if(Day<0)
        {
            *this+=(-Day);
            return *this;
        }
        _day-=Day;
        while(_day<=0)
        {
            --_month;
            if(_month<1)
            {
                _year--;
                _month=12;
            }
            _day+=getmonth(_year,_month);
        }
        return *this;
    }

-:

Date operator-(const int Day)
    {
        Date tmp=*this;
        return tmp-=Day;
    }

整體邏輯與加法大差不差,不過多贅述.

10. 前置++與后置++

前置++

Date& operator++()
    {
        *this+=1;
        return *this;
    }

若我想要將一個Date對象執(zhí)行++操作,則直接:++Date即可.

后置++:為了和前置++再一次發(fā)生重載,加入了一個參數(shù),這個參數(shù)在重載過程中并不會起到什么作用,僅為分辨具體是哪個重載,使用時編譯器會自己在后置++中傳入0,我們僅需正常使用即可,

Date operator++(int)
    {
        Date tmp=*this;
        *this+=1;
        return tmp;
    }

在剛學習c的階段,總會看到討論關(guān)于前置++與后置++的討論,現(xiàn)在看重載就知道了,因為后置++會拷貝一份原始值,所以效率會低一些.

不過在內(nèi)置類型中,這種效率變換可以忽略不計.

11.前置–與后置–

 Date& operator--()
    {
        *this-=1;
        return *this;
    }

    Date operator--(int)
    {
        Date tmp;
        *this-=1;
        return tmp;
    }

12.邏輯運算符-的重載

為兩個日期類間想減,計算日期間的差值

int operator-(Date &d)
    {
        Date max=*this;
        Date min=d;
        int flag=1;
        if(max<min)
        {
            max=d;
            min=*this;
            flag=-1;
        }
        int n=0;
        while(min!=max)
        {
            ++min;
            ++n;
        }
        return n*flag;
    }

先找出最大的日期,通過將最小的++與計數(shù)天數(shù)++,一步步逼近最大的天數(shù),最后返回,注意傳值需要傳引用,提高效率

13.流運算符重載

為什么在c++中cout/cin可以輸出/輸入任意內(nèi)置類型的對象,而不用帶對象類型呢?因為在c++中cout與cin也為一個流對象,其底層實現(xiàn)了多個類型的重載

此重載需要定義在全局中,若定義在類中,根據(jù)上方的轉(zhuǎn)換法則,則會變成d1<<cout,但定義在全局中,會出現(xiàn)訪問不了私有變量的情況,所以我們提供了一個友元函數(shù)的聲明.

  friend ostream& operator<<(ostream& out,const Date&d);
  friend istream& operator>>(istream& in, Date&d);

放在類中哪里都可以,表示這個函數(shù)是這個類的朋友,可以直接訪問其中的變量與函數(shù)(關(guān)于友元的具體含義之后會細講,)

13.1輸出流重載:

ostream& operator<<(ostream& out,const Date&d)
{
   out<<"day: "<<d._day<<" month: "<<d._month<<" year: "<<d._year<<endl;
   return out;
}

ostream為輸出流對象,其返回值會放進輸出流在輸出

13.2輸入流重載:

istream& operator>>(istream& in,Date&d)
{
   	int year, month, day;
	in >> day >> month >>year;

	if (month > 0 && month < 13
		&& day > 0 && day <= d.getmonth(year, month))
	{
		d._year = year;
		d._month = month;
		d._day = day;
	}
	else
	{
		cout << "非法日期" << endl;
	}
	return in;
}

整體與上方相同

14.完整代碼:

#include<iostream>
using namespace std;
class Date{
    
public:
    
    friend ostream& operator<<(ostream& out,const Date&d);
    friend istream& operator>>(istream& in, Date&d);
   
    Date(int day=1,int month=1,int year=1)
    {
        if(month>0&&month<13&&day>0&&day<getmonth(year,month))
            _day=day,_month=month,_year=year;
        else
            cout<<"輸入錯誤";
    }

    Date(const Date&d)
    {
        _day=d._day;
        _month=d._month;
        _year=d._year;
        cout<<"copy"<<endl;
    }

    int getmonth(int year,int month)
    {
        static int monthday[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
        if((year%4==0&&year%100!=0)||year%400==0)
        {
            if(month==2)return 29;
        }
        return monthday[month];
    }

    void print()
    {
        cout<<"day: "<<_day<<" month: "<<_month<<" year: "<<_year<<endl;
    }


    Date operator=(const Date d)
    {
        _day=d._day;
        _month=d._month;
        _year=d._year;
        return *this;
    }


    Date& operator+=(int Day)
    {
        if(Day<0)
        {
            *this-=(-Day);
            return *this;
        }
        _day+=Day;
        while(_day>getmonth(_year,_month))
        {
            _day-=getmonth(_year,_month);
            ++_month;
            if(_month>12)
            {
                _month=1;
                _year++;
            }
        }
        return *this;
    }
    Date operator+(int day)
    {
        Date tmp=*this;
        tmp+=day;
        tmp.print();
        return tmp;
    }
    Date& operator++()
    {
        *this+=1;
        return *this;
    }
    Date operator++(int)
    {
        Date tmp=*this;
        *this+=1;
        return tmp;
    }

    int operator-(Date &d)
    {
        Date max=*this;
        Date min=d;
        int flag=1;
        if(max<min)
        {
            max=d;
            min=*this;
            flag=-1;
        }
        int n=0;
        while(min!=max)
        {
            ++min;
            ++n;
        }
        return n*flag;
    }
    
    Date& operator-=(const int Day)
    {
        if(Day<0)
        {
            *this+=(-Day);
            return *this;
        }
        _day-=Day;
        while(_day<=0)
        {
            --_month;
            if(_month<1)
            {
                _year--;
                _month=12;
            }
            _day+=getmonth(_year,_month);
        }
        return *this;
    }
    
    Date operator-(const int Day)
    {
        Date tmp=*this;
        return tmp-=Day;
    }

    Date& operator--()
    {
        *this-=1;
        return *this;
    }

    Date operator--(int)
    {
        Date tmp;
        *this-=1;
        return tmp;
    }



    bool operator==(const Date&d)const
    {
        if(_year==d._year&&_month==d._month&&_day==d._day)
        {
            return true;
        }
        return false;
    }
    bool operator!=(const Date&d)const
    {
        if(*this==d)return false;
        return true;
    }
    bool operator<(const Date &d)const
    {
        if(_year<d._year)
        {
            return true;
        }
        if(_year==d._year&&_month<d._month)
        {
            return true;
        }
        if(_year==d._year&&_month==d._month&&_day<d._day)
        {
            return true;
        }
        return false;  
    }

    bool operator<=(const Date &d)const
    {
        return *this<d||*this==d;
    }

    bool operator>(const Date &d)const
    {
        return (!(*this<d)&&(*this!=d))?true:false;
    }
    bool operator>=(const Date &d)const
    {
        return !(*this<d);
    }


private:
    int _year;
    int _month;
    int _day;
};

ostream& operator<<(ostream& out,const Date&d)
{
   out<<"day: "<<d._day<<" month: "<<d._month<<" year: "<<d._year<<endl;
   return out;
}

istream& operator>>(istream& in,Date&d)
{
   	int year, month, day;
	in >> day >> month >>year;

	if (month > 0 && month < 13
		&& day > 0 && day <= d.getmonth(year, month))
	{
		d._year = year;
		d._month = month;
		d._day = day;
	}
	else
	{
		cout << "非法日期" << endl;
	}
	return in;
}

int main()
{
     
    Date d1(2,5,2024);
    d1+=100;
    d1.print();
}

至此日期類整體完成

15. 取地址運算符重載

class Date
{
public :
	Date* operator&()
	{
		return this ;
	}
	const Date* operator&()const
    {
    	return this ;
    }
private :
    int _year ; 
    int _month ; 
    int _day ; 
};  

默認情況下,編譯器會自動生成這個重載,大多數(shù)情況下我們也不需要寫這個重載.

若不想讓一個人獲得可修改地址,僅想讓其獲得不可修改的const地址,可以這樣寫

class Date
{
public :
	Date* operator&()
	{
		return NULL ;
	}
	const Date* operator&()const
    {
    	return this ;
    }
private :
    int _year ; 
    int _month ; 
    int _day ; 
};  

16.至此六個內(nèi)置類型成員函數(shù)完結(jié)

【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II文章來源地址http://www.zghlxwxcb.cn/news/detail-446384.html

到了這里,關(guān)于【C++技能樹】令常規(guī)運算符用在類上 --類的六個成員函數(shù)II的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【C++】運算符重載案例 - 字符串類 ⑤ ( 重載 大于 > 運算符 | 重載 小于 < 運算符 | 重載 右移 >> 運算符 - 使用全局函數(shù)重載 | 代碼示例 )

    使用 成員函數(shù) 實現(xiàn) 等于判斷 == 運算符重載 : 首先 , 寫出函數(shù)名 , 函數(shù)名規(guī)則為 \\\" operate \\\" 后面跟上要重載的運算符 , 要對 String a , b 對象對比操作 , 使用 大于 運算符 , 使用時用法為 a b ; 函數(shù)名是 operate ; 然后 , 根據(jù)操作數(shù) 寫出函數(shù)參數(shù) , 參數(shù)一般都是 對象的引用 ; 要對

    2024年02月07日
    瀏覽(27)
  • 【C++】運算符重載

    目錄 1. 基本概念 1.1 直接調(diào)用一個重載的運算符函數(shù) 1.2 某些運算符不應該被重載 1.3 使用與內(nèi)置類型一致的含義 1.4 賦值和復合賦值運算符 1.5 選擇作為成員或者非成員 2. 輸入和輸出運算符 2.1 輸出運算符重載 2.2 輸入運算符重載 3. 算術(shù)和關(guān)系運算符 3.1 算數(shù)運算符重載 3.2

    2024年02月11日
    瀏覽(32)
  • C++——運算符重載

    C++——運算符重載

    運算符重載,就是對已有的運算符重新進行定義,賦予其另一種功能,以適應不同的數(shù)據(jù)類型。 運算符重載的目的是讓語法更加簡潔 運算符重載不能改變本來寓意,不能改變基礎(chǔ)類型寓意 運算符重載的本質(zhì)是另一種函數(shù)調(diào)用(是編譯器去調(diào)用) 這個函數(shù)統(tǒng)一的名字叫opera

    2024年02月16日
    瀏覽(34)
  • C++:重載運算符

    C++:重載運算符

    1.重載不能改變運算符運算的對象個數(shù) 2.重載不能改變運算符的優(yōu)先級別 3.重載不能改變運算符的結(jié)合性 4.重載運算符必須和用戶定義的自定義類型的對象一起使用,其參數(shù)至少應該有一個是類對象,或類對象的引用 5.重載運算符的功能要類似于該運算符作用于標準類型數(shù)據(jù)

    2024年02月10日
    瀏覽(20)
  • c++ %運算符

    運算符%俗稱“取余”或“取模”運算符,負責計算兩個整數(shù)相除所得的余數(shù)。 在除法運算中,如果兩個運算對象的符號相同則商為正(如果不為0的話),否則商為負。C++語言的早期版本允許結(jié)果為負值的商向上或向下取整, C++11新標準則規(guī)定商一律向0取整(即直接切除小數(shù)部分

    2024年02月19日
    瀏覽(17)
  • c++基礎(chǔ)-運算符

    c++基礎(chǔ)-運算符

    目錄 1關(guān)系運算符 2運算符優(yōu)先級 3關(guān)系表達式的書寫 代碼實例: 下面是面試中可能遇到的問題: C++中有6個關(guān)系運算符,用于比較兩個值的大小關(guān)系,它們分別是: 運算符 描述 == 等于 != 不等于 小于 大于 = 小于等于 = 大于等于 這些運算符返回一個布爾值,即 true 或 false 。

    2024年02月02日
    瀏覽(25)
  • C++ 運算符

    運算符是一種告訴編譯器執(zhí)行特定的數(shù)學或邏輯操作的符號。C++ 內(nèi)置了豐富的運算符,并提供了以下類型的運算符: 算術(shù)運算符 關(guān)系運算符 邏輯運算符 位運算符 賦值運算符 雜項運算符 本章將逐一介紹算術(shù)運算符、關(guān)系運算符、邏輯運算符、位運算符、賦值運算符和其他

    2024年02月08日
    瀏覽(17)
  • C++ 條件運算符 ? :

    其中,Exp1、Exp2 和 Exp3 是表達式。請注意冒號的使用和位置。? : 表達式的值取決于 Exp1 的計算結(jié)果。如果 Exp1 為真,則計算 Exp2 的值,且 Exp2 的計算結(jié)果則為整個 ? : 表達式的值。如果 Exp1 為假,則計算 Exp3 的值,且 Exp3 的計算結(jié)果則為整個 ? : 表達式的值。 ? 被稱為三元運

    2024年02月11日
    瀏覽(23)
  • 把你的 Python 技能從 “Hello World“ 升級到 “萬能鑰匙“:掌握 Python 的輸出、輸入、數(shù)據(jù)類型轉(zhuǎn)換和運算符!

    把你的 Python 技能從 “Hello World“ 升級到 “萬能鑰匙“:掌握 Python 的輸出、輸入、數(shù)據(jù)類型轉(zhuǎn)換和運算符!

    這篇文章我將為大家分享 python 的輸出、輸入、數(shù)據(jù)類型的轉(zhuǎn)換和運算符 相關(guān)的知識。如果大家也想跟著博主一起學習 python ,歡迎訂閱專欄哦python學習?? 我們都知道,要想知道程序的運行結(jié)果,就需要將結(jié)果給打印到屏幕上,那么 python 是怎樣將程序輸出到屏幕上的呢?這

    2024年02月11日
    瀏覽(20)
  • 復習 --- C++運算符重載

    .5 運算符重載 運算符重載概念:對已有的運算符重新進行定義,賦予其另外一種功能,以適應不同的數(shù)據(jù)類型 4.5.1 加號運算符重載 作用:實現(xiàn)兩個自定義數(shù)據(jù)類型相加的運算 4.5.2 左移運算符重載 4.5.3遞增運算符重載 作用:通過重載遞增運算符,實現(xiàn)自己的整型數(shù)據(jù) 4.5.4 賦

    2024年02月07日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包