国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

手機(jī)網(wǎng)站建設(shè) 豆丁關(guān)鍵詞挖掘長(zhǎng)尾詞工具

手機(jī)網(wǎng)站建設(shè) 豆丁,關(guān)鍵詞挖掘長(zhǎng)尾詞工具,鐘樓做網(wǎng)站,廣州網(wǎng)頁(yè)設(shè)計(jì)公司招聘本文已收錄至《C語(yǔ)言》專欄! 作者:ARMCSKGT 目錄 前言 正文 構(gòu)造函數(shù) 對(duì)比C和C的初始化 構(gòu)造函數(shù)的使用與特性 默認(rèn)構(gòu)造函數(shù) C11關(guān)于默認(rèn)構(gòu)造缺陷的補(bǔ)丁 析構(gòu)函數(shù) 析構(gòu)函數(shù)特性 默認(rèn)析構(gòu)和自定義析構(gòu) 拷貝構(gòu)造函數(shù) 問(wèn)題聚焦 拷貝構(gòu)造的定…

? ? ??

本文已收錄至《C++語(yǔ)言》專欄!
作者:ARMCSKGT

? ? ??


目錄

前言?

正文

構(gòu)造函數(shù)

對(duì)比C和C++的初始化

構(gòu)造函數(shù)的使用與特性

默認(rèn)構(gòu)造函數(shù)

C++11關(guān)于默認(rèn)構(gòu)造缺陷的補(bǔ)丁

析構(gòu)函數(shù)

析構(gòu)函數(shù)特性

默認(rèn)析構(gòu)和自定義析構(gòu)

拷貝構(gòu)造函數(shù)

問(wèn)題聚焦?

拷貝構(gòu)造的定義和特性

使用場(chǎng)景

構(gòu)造函數(shù)小結(jié)

運(yùn)算符重載

定義方式

特性

使用說(shuō)明

運(yùn)算符重載原理

賦值運(yùn)算符重載

前后置++和--

const修飾this

取地址重載和const取地址重載

最后


前言?

C++類在設(shè)計(jì)之時(shí),規(guī)定類中有六個(gè)默認(rèn)的成員函數(shù),這些成員函數(shù)天生就存在,而且功能都很強(qiáng)大,類和對(duì)象的關(guān)鍵點(diǎn)就在這六個(gè)默認(rèn)成員函數(shù)的學(xué)習(xí),本篇將會(huì)逐一介紹這六個(gè)成員函數(shù),讓我們向類和對(duì)象的深處出發(fā)!


正文

C++規(guī)定在每個(gè)類中有六個(gè)默認(rèn)函數(shù)成員:

函數(shù)功能重要性
構(gòu)造函數(shù)定義和初始化成員變量重要
析構(gòu)函數(shù)釋放申請(qǐng)的內(nèi)存空間(銷毀成員變量)重要
拷貝構(gòu)造(函數(shù))實(shí)現(xiàn)對(duì)象間的深拷貝重要
賦值重載(函數(shù))實(shí)現(xiàn)對(duì)象間的深賦值重要
取地址重載(函數(shù))自定義類對(duì)象取地址操作符功能一般
const取地址重載(函數(shù))自定義對(duì)象取地址操作符功能const修飾返回的地址一般

這些函數(shù)我們不寫,編譯器也會(huì)自己寫一個(gè)默認(rèn)的函數(shù)代替對(duì)應(yīng)函數(shù)!

//以日期類的方式初見六大默認(rèn)成員函數(shù)
class Date
{
public://構(gòu)造函數(shù)Date(size_t year = 1970, size_t month = 1, size_t day = 1){_year = year;_month = month;_day = day;}//析構(gòu)函數(shù)~Date(){_year = 0;_month = 0;_day = 0;}//拷貝構(gòu)造函數(shù)(簡(jiǎn)稱:拷貝構(gòu)造)Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//賦值重載函數(shù)(賦值運(yùn)算符重載)Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}//取地址運(yùn)算符重載Date* operator&(){return this;}//const返回取地址運(yùn)算符重載,const修飾thisconst Date* operator&() const{return this;}private:size_t _year;size_t _month;size_t _day;};


構(gòu)造函數(shù)


對(duì)比C和C++的初始化

我們?cè)谑褂肅語(yǔ)言實(shí)現(xiàn)一些例如順序表,棧等簡(jiǎn)單數(shù)據(jù)結(jié)構(gòu)時(shí),一般都會(huì)寫一個(gè)初始化函數(shù)Init,防止野指針訪問(wèn),但這樣很容易讓我們忘記去調(diào)用!

?

在C++中,為了避免這種事情,引入了構(gòu)造函數(shù),在對(duì)象實(shí)例化時(shí)編譯器自動(dòng)調(diào)用構(gòu)造函數(shù)進(jìn)行初始化,所以構(gòu)造函數(shù)是為對(duì)象自動(dòng)初始化而生的!

?

我們以日期對(duì)象為例,對(duì)比C與C++的初始化方案:

//C語(yǔ)言實(shí)現(xiàn)日期功能
typedef struct C_Date //日期數(shù)據(jù)結(jié)構(gòu)體
{size_t _year;size_t _month;size_t _day;
}C_Date;void InitDate(C_Date* L)//初始化函數(shù)
{L->_year = 0;L->_month = 0;L->_day = 0;
}
//C++實(shí)現(xiàn)日期類
class CPP_Date //日期對(duì)象
{
public://默認(rèn)構(gòu)造CPP_Date(size_t year){_year = year;_month = 1;_day = 1;}//重載實(shí)現(xiàn)多種默認(rèn)構(gòu)造方式CPP_Date(size_t year, size_t month, size_t day){_year = year;_month = month;_day = day;}private:size_t _year;size_t _month;size_t _day;
};

可以發(fā)現(xiàn)C++中類融入構(gòu)造函數(shù)后只需要實(shí)例化對(duì)象就能同時(shí)完成初始化,非常方便!而且結(jié)合C++的缺少參數(shù),函數(shù)重載等新特性,可以讓初始化豐富多樣,增強(qiáng)程序可用性!

??

對(duì)比C與C++,可以發(fā)現(xiàn)C++非常貼心,就像汽車中的手動(dòng)擋與自動(dòng)擋,但兩者在不同場(chǎng)合各有千秋,在程序開發(fā)上C++的更勝一籌,在較為底層且需要更細(xì)節(jié)的程序控制時(shí)C語(yǔ)言更勝一籌!不過(guò)一般在程序開發(fā)中,C與C++可以搭配一起編程!


構(gòu)造函數(shù)的使用與特性

構(gòu)造函數(shù)是一個(gè)特殊的成員函數(shù),名字與類名相同,創(chuàng)建類類型對(duì)象時(shí)由編譯器自動(dòng)調(diào)用,以保證每個(gè)數(shù)據(jù)成員都有 一個(gè)合適的初始值,并且在對(duì)象整個(gè)生命周期內(nèi)只調(diào)用一次(實(shí)例化時(shí)被編譯器調(diào)用)。

?

構(gòu)造函數(shù)是特殊的成員函數(shù),需要注意的是,構(gòu)造函數(shù)雖然名稱叫構(gòu)造,但是構(gòu)造函數(shù)的主要任務(wù)并不是開空間創(chuàng)建對(duì)象,而是初始化對(duì)象成員變量。
?

構(gòu)造函數(shù)的定義方式:

class Test
{
public: //構(gòu)造函數(shù)必須公開Test(參數(shù)) {}  //構(gòu)造函數(shù)的函數(shù)名與類名相同且沒(méi)有返回值
};

構(gòu)造函數(shù)的特性

  • 函數(shù)名與類名相同。
  • 無(wú)返回值(不需要寫返回值類型,void也不需要寫)。
  • 對(duì)象實(shí)例化時(shí)編譯器自動(dòng)調(diào)用對(duì)應(yīng)的構(gòu)造函數(shù)。
  • 構(gòu)造函數(shù)可以重載,支持多個(gè)構(gòu)造函數(shù),但是默認(rèn)的構(gòu)造函數(shù)只有一個(gè)。

使用構(gòu)造函數(shù)初始化日期對(duì)象:

//C++實(shí)現(xiàn)日期類
class CPP_Date //日期對(duì)象
{
public://默認(rèn)構(gòu)造函數(shù)只允許出現(xiàn)一種顯示,如果定義全缺省就可以代替默認(rèn)構(gòu)造了//CPP_Date()//默認(rèn)構(gòu)造函數(shù)初始化-功能比較局限//{//	_year = 0;//	_month = 0;//	_day = 0;//}//構(gòu)造函數(shù)可以重載實(shí)現(xiàn)多種構(gòu)造方式CPP_Date(size_t year){_year = year;_month = 1;_day = 1;}//一般使用全缺省值方式代替默認(rèn)構(gòu)造-智能方便CPP_Date(size_t year = 1970, size_t month = 1, size_t day = 1){_year = year;_month = month;_day = day;}private:size_t _year;size_t _month;size_t _day;
};int main()
{//CPP_Date d(); //注意:這種調(diào)用默認(rèn)構(gòu)造的方式是錯(cuò)誤的,調(diào)用默認(rèn)構(gòu)造不需要加()CPP_Date d1;CPP_Date d2(2022);CPP_Date d3(2023,3,12);//可以通過(guò)調(diào)用不同的構(gòu)造函數(shù)實(shí)例化多個(gè)不同的對(duì)象
}


默認(rèn)構(gòu)造函數(shù)

如果類中沒(méi)有顯式定義構(gòu)造函數(shù),則C++編譯器會(huì)自動(dòng)生成一個(gè)無(wú)參的默認(rèn)構(gòu)造函數(shù),一旦
用戶顯式定義編譯器將不再生成。

那有人可能會(huì)問(wèn),既然編譯器會(huì)自動(dòng)生成構(gòu)造函數(shù),我們?yōu)槭裁催€要去寫?

注意:編譯器生成的默認(rèn)構(gòu)造函數(shù),對(duì)內(nèi)置類型不做處理,對(duì)自定義類型會(huì)調(diào)用該對(duì)象的構(gòu)造函數(shù)!

數(shù)據(jù)類型區(qū)分

  • 內(nèi)置類型:int,char,double等。
  • 自定義類型:struct,class等,這些自定義類型可以有自己的默認(rèn)構(gòu)造函數(shù)。

編譯器默認(rèn)構(gòu)造對(duì)內(nèi)置類型的初始化:?

編譯器默認(rèn)構(gòu)造初始化內(nèi)置類型

自定義默認(rèn)構(gòu)造:

//C++實(shí)現(xiàn)日期類
class CPP_Date //日期對(duì)象
{
public://無(wú)參構(gòu)造函數(shù)//CPP_Date()//{//	_year = 0;//	_month = 0;//	_day = 0;//}//全缺省默認(rèn)構(gòu)造CPP_Date(size_t year = 1970, size_t month = 1, size_t day = 1){_year = year;_month = month;_day = day;}//當(dāng)存在兩種實(shí)例化相同的構(gòu)造方法時(shí),只能存在一種,否則在調(diào)用時(shí)會(huì)出錯(cuò)!//例如 (CPP_Date d;) 編譯器無(wú)法判斷d對(duì)象調(diào)用的是哪一個(gè)構(gòu)造函數(shù)private:size_t _year;size_t _month;size_t _day;
};
自定義默認(rèn)構(gòu)造完成內(nèi)置類型的初始化

??

無(wú)參的構(gòu)造函數(shù)和全缺省的構(gòu)造函數(shù)都稱為默認(rèn)構(gòu)造函數(shù),并且默認(rèn)構(gòu)造函數(shù)只能有一個(gè)。

?
注意:無(wú)參構(gòu)造函數(shù)、全缺省構(gòu)造函數(shù)、我們沒(méi)寫編譯器默認(rèn)生成的構(gòu)造函數(shù),都可以認(rèn)為是默認(rèn)構(gòu)造函數(shù)。


C++11關(guān)于默認(rèn)構(gòu)造缺陷的補(bǔ)丁

為了解決內(nèi)置類型無(wú)法被編譯器生成的默認(rèn)構(gòu)造初始化的問(wèn)題,在C++11中支持內(nèi)置類型在聲明階段給缺省值,當(dāng)編譯器生成默認(rèn)構(gòu)造函數(shù)時(shí),使用這些缺省值初始化內(nèi)置類型。

class CPP_Date //日期對(duì)象
{
public:private:size_t _year = 1970; //聲明階段賦予缺省值size_t _month = 1;size_t _day = 1;//注意:類成員變量定義在構(gòu)造函數(shù)的初始化列表,并不是在聲明階段!
};


所以,對(duì)于內(nèi)置類型要么自定義默認(rèn)構(gòu)造函數(shù),或者在聲明時(shí)賦予缺省值,對(duì)于自定義類型編譯器會(huì)調(diào)用對(duì)應(yīng)的構(gòu)造函數(shù)!


析構(gòu)函數(shù)


我們?cè)趯戫樞虮頃r(shí),在結(jié)束使用時(shí)需要調(diào)用銷毀函數(shù)是否內(nèi)存空間,但是我們可能經(jīng)常也會(huì)忘記釋放空間,析構(gòu)函數(shù)就是用來(lái)銷毀對(duì)象和釋放空間的

??

析構(gòu)函數(shù)是特殊的成員函數(shù),其功能與構(gòu)造函數(shù)相反,析構(gòu)函數(shù)不是完成對(duì)對(duì)象本身的銷毀,局部對(duì)象銷毀工作是由編譯器完成的。而對(duì)象在銷毀時(shí)(生命周期結(jié)束時(shí))會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù),完成對(duì)象中資源的清理工作。


析構(gòu)函數(shù)特性

  • 析構(gòu)函數(shù)名是在類名前加上字符 ~。
  • 無(wú)參數(shù)無(wú)返回值類型(void也不需要寫)。
  • 一個(gè)類只能有一個(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ù)。
    ? ?

對(duì)于析構(gòu)函數(shù),最大的特性是在對(duì)象生命周期結(jié)束時(shí)被自動(dòng)調(diào)用,與構(gòu)造函數(shù)的區(qū)別在于不支持重載,也就是說(shuō)一個(gè)對(duì)象只能有一個(gè)析構(gòu)函數(shù)!


默認(rèn)析構(gòu)和自定義析構(gòu)

??

如果我們不寫析構(gòu)函數(shù),編譯器也會(huì)默認(rèn)生成,但編譯器生成的析構(gòu)函數(shù)對(duì)內(nèi)置類型仍然不做處理,對(duì)自定義類型會(huì)調(diào)用對(duì)應(yīng)的析構(gòu)函數(shù)處理

?

//析構(gòu)函數(shù)定義
class Test
{~Test() {//釋放方法}
};
//簡(jiǎn)易棧對(duì)象
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申請(qǐng)空間失敗!!!");return;}_capacity = capacity;_size = 0;cout << "構(gòu)造函數(shù)初始化棧對(duì)象" << endl;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}// 其他方法...~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}cout << "析構(gòu)函數(shù)釋放棧對(duì)象空間" << endl;}
private:DataType* _array;int _capacity;int _size;
};

對(duì)于自定義類型和內(nèi)置類型,是否存在析構(gòu)函數(shù)進(jìn)行釋放影響都不大,當(dāng)涉及我們自己動(dòng)態(tài)開辟空間時(shí),就需要使用析構(gòu)函數(shù)釋放空間


注意:創(chuàng)建哪個(gè)類的對(duì)象則調(diào)用該類的析構(gòu)函數(shù),銷毀那個(gè)類的對(duì)象則調(diào)用該類的析構(gòu)函數(shù)!對(duì)于析構(gòu)函數(shù),只要是對(duì)象中涉及動(dòng)態(tài)內(nèi)存申請(qǐng),則需要使用析構(gòu)函數(shù)釋放!


拷貝構(gòu)造函數(shù)


拷貝構(gòu)造也是構(gòu)造函數(shù)的一種,但是參數(shù)不同則構(gòu)成重載,功能和特性與構(gòu)造函數(shù)不同!


問(wèn)題聚焦?

我們?cè)趧?chuàng)建對(duì)象時(shí),如果需要拷貝一個(gè)一模一樣的對(duì)象,也就是復(fù)制一個(gè)對(duì)象;那么就需要?jiǎng)?chuàng)建一個(gè)一模一樣的對(duì)象后將數(shù)據(jù)拷貝一份過(guò)去。

編譯器默認(rèn)生成的拷貝構(gòu)造函數(shù)只支持淺拷貝,也就是值拷貝,對(duì)于內(nèi)置類型,淺拷貝是沒(méi)有影響的,但是如果對(duì)象中申請(qǐng)了空間,那么該對(duì)象中必定有一個(gè)指針指向該空間的首地址,淺拷貝只會(huì)講該地址拷貝一份給另一個(gè)對(duì)象,那么會(huì)導(dǎo)致一個(gè)嚴(yán)重的問(wèn)題,就是兩個(gè)對(duì)象申請(qǐng)的空間是同一個(gè)地址,在增刪查改和析構(gòu)時(shí)拷貝的對(duì)象析構(gòu)函數(shù)會(huì)對(duì)同一片空間進(jìn)行修改和重復(fù)釋放一片空間導(dǎo)致異常,最后成為野指針問(wèn)題

淺拷貝只是簡(jiǎn)單的逐字節(jié)拷貝,對(duì)于對(duì)象內(nèi)部有空間申請(qǐng)的,會(huì)發(fā)生共用空間重復(fù)析構(gòu)的情況;而深拷貝是在新對(duì)象中開辟一塊屬于自己的新空間,然后將數(shù)據(jù)逐一拷貝過(guò)來(lái),新舊對(duì)象之間的數(shù)據(jù)相互獨(dú)立!

?

淺拷貝下對(duì)象共用一塊空間


拷貝構(gòu)造的定義和特性

??

拷貝構(gòu)造函數(shù):只有單個(gè)形參,該形參是對(duì)本類類型對(duì)象的引用(一般常用const修飾),在用已存在的類類型對(duì)象創(chuàng)建新對(duì)象時(shí)由編譯器自動(dòng)調(diào)用。

? ?

特性

  • 拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個(gè)重載形式。
  • 拷貝構(gòu)造函數(shù)的參數(shù)只有一個(gè)且必須是類類型對(duì)象的引用,使用傳值方式編譯器直接報(bào)錯(cuò),因?yàn)闀?huì)引發(fā)無(wú)窮遞歸調(diào)用。
    ?

定義和調(diào)用

class Test
{//拷貝構(gòu)造形參的定義方式是唯一的:(const 類型& )Test(const Test& T) {//拷貝方法} //定義方式
};int main()
{Test t1;Test t2(t1); //調(diào)用拷貝構(gòu)造方式一Test t3 = t2; //調(diào)用拷貝構(gòu)造方式二return 0;
}

? ?

定義須知

  • 編譯器默認(rèn)生成的拷貝構(gòu)造,只是簡(jiǎn)單拷貝,只能用于非動(dòng)態(tài)內(nèi)存開辟的空間
  • 拷貝構(gòu)造的參數(shù)定義方式是唯一的??
  • 拷貝構(gòu)造函數(shù)函數(shù)名與構(gòu)造函數(shù)相同,不過(guò)參數(shù)類型為類對(duì)象的引用,不加引用則會(huì)發(fā)生無(wú)窮拷貝(因?yàn)樾螀⑹强截惗鴣?lái)的,這樣形參會(huì)陷入無(wú)限遞歸拷貝形參)
形參無(wú)窮遞歸拷貝

使用場(chǎng)景

//日期類示例
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) // 錯(cuò)誤寫法:編譯報(bào)錯(cuò),會(huì)引發(fā)無(wú)窮遞歸{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(d1); //拷貝構(gòu)造方式一Date d3 = d2; //拷貝構(gòu)造方式二return 0;
}

像日期類這樣沒(méi)有動(dòng)態(tài)內(nèi)存申請(qǐng)的對(duì)象,使用編譯器默認(rèn)生成的拷貝構(gòu)造進(jìn)行淺拷貝即可,但是向數(shù)據(jù)結(jié)構(gòu)需要動(dòng)態(tài)內(nèi)存申請(qǐng)等相對(duì)復(fù)雜的對(duì)象,就需要自定義拷貝構(gòu)造實(shí)現(xiàn)深拷貝

? ??

拷貝構(gòu)造函數(shù)典型調(diào)用場(chǎng)景

  • 使用已存在對(duì)象創(chuàng)建新對(duì)象
  • 函數(shù)參數(shù)類型為類類型對(duì)象
  • 函數(shù)返回值類型為類類型對(duì)象

說(shuō)明

  • 對(duì)于深拷貝,是有一定代價(jià)的,為了提高程序效率,一般對(duì)象傳參時(shí),盡量使用引用類型,返回時(shí)根據(jù)實(shí)際場(chǎng)景,能用引用盡量使用引用!
  • 默認(rèn)拷貝構(gòu)造函數(shù)與默認(rèn)構(gòu)造函數(shù)名相同,當(dāng)我們只寫拷貝而不寫構(gòu)造時(shí),編譯器就會(huì)報(bào)錯(cuò),因?yàn)榇藭r(shí)的拷貝會(huì)被誤以為是默認(rèn)構(gòu)造函數(shù)也就是說(shuō),默認(rèn)拷貝構(gòu)造函數(shù)存在的前提是默認(rèn)構(gòu)造函數(shù)已存在

構(gòu)造函數(shù)小結(jié)


構(gòu)造大家族到這里基本內(nèi)容就介紹的差不多了!

類型用途處理情況
構(gòu)造函數(shù)初始化對(duì)象不對(duì)內(nèi)置類型作處理,自定義類型調(diào)用對(duì)應(yīng)構(gòu)造函數(shù)
析構(gòu)函數(shù)銷毀對(duì)象也不對(duì)內(nèi)置類型作處理,自定義類型調(diào)用對(duì)應(yīng)析構(gòu)函數(shù)
拷貝構(gòu)造函數(shù)拷貝對(duì)象只能對(duì)簡(jiǎn)單內(nèi)置類型做處理,自定義類型需要自己實(shí)現(xiàn)深拷貝

運(yùn)算符重載


C++為了增強(qiáng)代碼的可讀性引入了運(yùn)算符重載,運(yùn)算符重載是具有特殊函數(shù)名的函數(shù),也具有其返回值類型,函數(shù)名字以及參數(shù)列表,其返回值類型與參數(shù)列表與普通的函數(shù)類似。

運(yùn)算符重載的引入,主要是為了解決基本運(yùn)算符功能不足以滿足自定義類型需求的情況,例如日期類的加減,以及前后置++和--等,需要自定義對(duì)象運(yùn)算符的功能!


定義方式

返回值類型 operator操作符(參數(shù))
{//自定義操作符功能
}// operator 是運(yùn)算符重載的關(guān)鍵字

特性

  • 不能通過(guò)連接其他符號(hào)來(lái)創(chuàng)建新的操作符:比如operator@

  • 重載操作符必須有一個(gè)類類型參數(shù)

  • 用于內(nèi)置類型的運(yùn)算符,其含義不能改變,例如:內(nèi)置的整型+,不 能改變其含義

  • 作為類成員函數(shù)重載時(shí),其形參看起來(lái)比操作數(shù)數(shù)目少一個(gè),因?yàn)槌蓡T函數(shù)的第一個(gè)參數(shù)為隱藏的this

  • 對(duì)于內(nèi)置運(yùn)算符,不能改變其含義

  • ?operator操作符 就是函數(shù)名

  • 注意這5個(gè)運(yùn)算符不能重載:(1)?.*?,(2)?:: ,(3)sizeof,(4)?:,(5)?.?


//日期類
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//為了保證封裝性,類成員變量一般是私有,所以運(yùn)算符重載一般定義在類內(nèi)部bool operator==(const Date& d){//這里相當(dāng)于 *this 與 d 的 == 比較return _year == d._year&& _month == d._month&& _day == d._day;}private:int _year;int _month;int _day;
};int main()
{Date d1(2018, 9, 26);Date d2(2018, 9, 27);cout << (d1 == d2) << endl; //這里相當(dāng)于調(diào)用 d1.operator==(d2)return 0;
}

使用說(shuō)明

  • operator 函數(shù)中的操作數(shù)取決于參數(shù)個(gè)數(shù)
  • operator 一般定義在類中,方便訪問(wèn)類成員,當(dāng)定義在類中時(shí),運(yùn)算符左邊的對(duì)象默認(rèn)是*this
  • operator 如果定義在類外,則無(wú)法訪問(wèn)類的所有成員,此時(shí)要么在類中定義特定函數(shù)獲取私有成員要么聲明為友元函數(shù),但是大部分場(chǎng)景下都沒(méi)有定義在類中更合適

運(yùn)算符重載原理

運(yùn)算符重載的原理與函數(shù)重載原理基本相同,也是對(duì)函數(shù)名修飾。

如果定義在類中在Linux環(huán)境下修飾規(guī)則為:_ZN4D+類名+運(yùn)算符英文簡(jiǎn)稱+ERKS_


賦值運(yùn)算符重載

通過(guò)上面的鋪墊,我們就要介紹下一個(gè)默認(rèn)成員,那就是賦值重載函數(shù)!

class Test
{};

賦值重載是將一個(gè)對(duì)象賦值給另一個(gè)對(duì)象,與拷貝構(gòu)造相似,但是拷貝構(gòu)造是通過(guò)一個(gè)對(duì)象去實(shí)例化一個(gè)相同的對(duì)象,而賦值重載的前提是兩個(gè)對(duì)象已經(jīng)實(shí)例化存在,相互之間再賦值!本質(zhì)區(qū)別在于:一個(gè)是對(duì)象尚未實(shí)例化,另一個(gè)是兩個(gè)對(duì)象都已存在!當(dāng)兩個(gè)對(duì)象都被創(chuàng)建,并發(fā)生賦值行為時(shí),才叫做賦值重載!

??

對(duì)于這種自定義類型復(fù)制的問(wèn)題,就會(huì)涉及深拷貝和淺拷貝的問(wèn)題,所以賦值重載是很有必要的!

//日期類
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}Date& operator=(const Date& d) //與拷貝構(gòu)造一樣能用引用就用引用{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this; //返回賦值的對(duì)象的引用(也就是自己)//這里之所以返回自己的引用是因?yàn)闀?huì)發(fā)生 d1 = d2 = d3 這樣連等的情況//使用引用可以有效避免拷貝}private:int _year;int _month;int _day;
};

賦值運(yùn)算符重載格式

  • 參數(shù)類型:const T&,傳遞引用可以提高傳參效率
  • 返回值類型:T&,返回引用可以提高返回的效率,有返回值目的是為了支持連續(xù)賦值
  • 檢測(cè)是否自己給自己賦值
  • 返回*this :要復(fù)合連續(xù)賦值的含義
  • 賦值運(yùn)算符只能重載成類的成員函數(shù)不能重載成全局函數(shù)

如果賦值運(yùn)算符重載成全局函數(shù),就沒(méi)有this指針了,需要給兩個(gè)參數(shù),而且此時(shí)編譯器就會(huì)報(bào)錯(cuò)error C2801: “operator =”必須是非靜態(tài)成員!

??
原因:賦值運(yùn)算符如果不顯式實(shí)現(xiàn),編譯器會(huì)生成一個(gè)默認(rèn)的。此時(shí)用戶再在類外自己實(shí)現(xiàn)一個(gè)全局的賦值運(yùn)算符重載,就和編譯器在類中生成的默認(rèn)賦值運(yùn)算符重載沖突了,故賦值運(yùn)算符重載只能是類的成員函數(shù)。

?默認(rèn)賦值重載函數(shù):用戶沒(méi)有顯式實(shí)現(xiàn)時(shí),編譯器會(huì)生成一個(gè)默認(rèn)賦值運(yùn)算符重載,以值的方式逐字節(jié)拷貝。

??

注意:內(nèi)置類型成員變量是直接賦值的,而自定義類型成員變量需要調(diào)用對(duì)應(yīng)類的賦值運(yùn)算符重載完成賦值。

??

所以賦值重載的使用環(huán)境與拷貝構(gòu)造類似:如果類中未涉及到動(dòng)態(tài)內(nèi)存申請(qǐng)(資源管理),賦值運(yùn)算符是否實(shí)現(xiàn)都可以;一旦涉及到資源管理則必須要實(shí)現(xiàn)!

//棧對(duì)象 - 猜猜是否會(huì)發(fā)生與拷貝構(gòu)造相同的問(wèn)題
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請(qǐng)空間失敗");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2;s2 = s1;return 0;
}


前后置++和--

對(duì)于自定義對(duì)象,前后置++和--還是經(jīng)常會(huì)使用到的!

class Test
{Test& operator++() {}  //前置++Test operator++(int) {} //后置++Test& operator--() {}  //前置--Test operator--(int) {} //后置--
};
//以日期類進(jìn)行介紹
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// 前置++:返回+1之后的結(jié)果
// 注意:this指向的對(duì)象函數(shù)結(jié)束后不會(huì)銷毀,故以引用方式返回提高效率Date& operator++(){_day += 1;return *this;}// 后置++:
// 注意:后置++是自己+1然后返回+1之前的值
// 而temp是臨時(shí)對(duì)象,因此只能以值的方式返回,不能返回引用Date operator++(int){Date temp(*this);_day += 1;return temp;}
private:int _year;int _month;int _day;
};int main()
{Date d1;d1++;++d1;return 0;
}

原理:前置++和后置++都是一元運(yùn)算符,為了讓前置++與后置++形成能正確重載,C++規(guī)定:后置++重載時(shí)多增加一個(gè)int類型的參數(shù),但調(diào)用函數(shù)時(shí)該參數(shù)不用傳遞,編譯器自動(dòng)傳遞(前后置--實(shí)現(xiàn)與++相同)。


const修飾this


將const修飾的“成員函數(shù)”稱之為const成員函數(shù),const修飾類成員函數(shù),實(shí)際修飾該成員函數(shù)隱含的this指針,表明在該成員函數(shù)中不能對(duì)類的任何成員進(jìn)行修改。

?

const常被用來(lái)修飾引用和指針,使用const修飾可以提高程序的健壯性!

使用場(chǎng)景

  • 被(指針)指向?qū)ο笫浅A粱蚺R時(shí)變量
  • 被引用對(duì)象是常亮或臨時(shí)變量

這些對(duì)象必須使用const修飾,避免權(quán)限放大的問(wèn)題!


修飾this指針格式

有小伙伴可能會(huì)疑惑,this指針我們不能顯示定義,那么如果要const修飾怎么辦?

對(duì)于this指針的修飾,格式為:

class Test
{void Fun() const //將const加在函數(shù)參數(shù)后即可{//函數(shù)方法}  
};
//設(shè)想以下日期類代碼的運(yùn)行結(jié)果
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}void Print() const{cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};int main()
{Date d1(2022, 1, 13);d1.Print();const Date d2(2022, 1, 13);d2.Print();return 0;
}
代碼運(yùn)行結(jié)果

總之,const修飾this指針可以起到權(quán)限平移的作用!


取地址重載和const取地址重載


這兩個(gè)默認(rèn)成員函數(shù)一般不用重新定義 ,編譯器默認(rèn)會(huì)生成。

class Date
{
public:Date* operator&() //返回對(duì)象的地址{return this;}const Date* operator&() const //返回const修飾對(duì)象的地址{return this;}
private:int _year; // 年int _month; // 月int _day; // 日
};

這兩個(gè)運(yùn)算符一般不需要重載,使用編譯器生成的默認(rèn)取地址的重載即可,只有特殊情況,才需要重載,比如想讓別人獲取到指定的內(nèi)容!


最后

以上就是 類和對(duì)象 - 中 的全部?jī)?nèi)容了,本篇介紹了類的六大默認(rèn)成員函數(shù),對(duì)于構(gòu)造函數(shù)何時(shí)用編譯器自動(dòng)生成的,何時(shí)自己實(shí)現(xiàn)都需要依照情況而定!對(duì)于每個(gè)成員其規(guī)則和細(xì)節(jié)都很多,需要我們?cè)陂L(zhǎng)期的使用中去牢固的掌握,掌握了這六大成員函數(shù)的使用,那么你將對(duì)類和對(duì)象的掌握又進(jìn)一步!

本次 <C++類和對(duì)象 - 中> 就介紹到這里啦,希望能夠盡可能幫助到大家。

如果文章中有瑕疵,還請(qǐng)各位大佬細(xì)心點(diǎn)評(píng)和留言,我將立即修補(bǔ)錯(cuò)誤,謝謝!

🌟其他文章閱讀推薦🌟

C++ 類和對(duì)象 - 上

C++ 入門知識(shí)

數(shù)據(jù)結(jié)構(gòu)初階?<棧>

🌹歡迎讀者多多瀏覽多多支持!🌹

http://aloenet.com.cn/news/42539.html

相關(guān)文章:

  • 為什么選php語(yǔ)言做網(wǎng)站手機(jī)百度網(wǎng)盤下載慢怎么解決
  • 三級(jí)分銷網(wǎng)站制作打開網(wǎng)址資料網(wǎng)站
  • 政府集約化網(wǎng)站群建設(shè)aso推廣公司
  • 鄭州小程序制作流程及費(fèi)用aso優(yōu)化服務(wù)
  • 網(wǎng)站頁(yè)面設(shè)計(jì)風(fēng)格今日網(wǎng)站收錄查詢
  • 德陽(yáng)企業(yè)品牌網(wǎng)站建設(shè)引流推廣廣告怎么寫
  • 怎么利用網(wǎng)站做cpa推廣傳播易廣告投放平臺(tái)
  • 網(wǎng)站必須備案嗎社群營(yíng)銷怎么做
  • 我要自學(xué)網(wǎng)ps視頻教程免費(fèi)寧波網(wǎng)站優(yōu)化公司哪家好
  • 自己開發(fā)一款游戲怎么做搜索引擎seo優(yōu)化
  • 企業(yè)網(wǎng)站手機(jī)版模板免費(fèi)下載上海關(guān)鍵詞優(yōu)化外包
  • php婚慶網(wǎng)站競(jìng)價(jià)賬戶托管哪家好
  • 大理市住房和城鄉(xiāng)建設(shè)局網(wǎng)站磁力棒
  • wordpress 漏洞 掃描seo網(wǎng)站推廣專員
  • web網(wǎng)站開發(fā)用什么語(yǔ)言網(wǎng)絡(luò)廣告電話
  • 服飾網(wǎng)站模板設(shè)計(jì)百度搜索引擎怎么弄
  • 廣西網(wǎng)站建設(shè)運(yùn)營(yíng)費(fèi)用專業(yè)代寫文案的公司
  • html網(wǎng)站開發(fā)工具有哪些互聯(lián)網(wǎng)登錄的網(wǎng)站名
  • 做sns網(wǎng)站需要什么百度熱線電話
  • 網(wǎng)站建設(shè)技術(shù)哪個(gè)好seo管理系統(tǒng)
  • qt科技感ui界面sem優(yōu)化軟件哪家好
  • 石家莊做網(wǎng)站價(jià)格網(wǎng)站優(yōu)化的關(guān)鍵詞
  • 網(wǎng)站做流量怎么賺錢的培訓(xùn)后的收獲和感想
  • 濟(jì)南網(wǎng)站建設(shè)工作室網(wǎng)球排名即時(shí)最新排名
  • 有沒(méi)有做網(wǎng)站的聯(lián)系方式經(jīng)典營(yíng)銷案例分析
  • 消費(fèi)返利系統(tǒng)網(wǎng)站建設(shè)廈門站長(zhǎng)優(yōu)化工具
  • 做電商網(wǎng)站注意什么問(wèn)題seo推廣代運(yùn)營(yíng)
  • 建設(shè)信用卡銀行積分商城網(wǎng)站福清網(wǎng)絡(luò)營(yíng)銷
  • 網(wǎng)站制作難點(diǎn)seo是做什么工作內(nèi)容
  • 網(wǎng)站設(shè)計(jì)流程電話站長(zhǎng)工具網(wǎng)