欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++超詳細(xì)講解運(yùn)算符重載

 更新時(shí)間:2022年06月02日 09:03:41   作者:iheal  
本文包括了對(duì)C++類的6個(gè)默認(rèn)成員函數(shù)中的賦值運(yùn)算符重載和取地址和const對(duì)象取地址操作符的重載。運(yùn)算符是程序中最最常見(jiàn)的操作,例如對(duì)于內(nèi)置類型的賦值我們直接使用=賦值即可,因?yàn)檫@些編譯器已經(jīng)幫我們做好了,但是對(duì)象的賦值呢?能直接賦值嗎

概念

C++為了增強(qiáng)代碼的可讀性引入了運(yùn)算符重載,運(yùn)算符重載是具有特殊函數(shù)名的函數(shù),也具有其返回值類

型,函數(shù)名字以及參數(shù)列表,其返回值類型與參數(shù)列表與普通的函數(shù)類似。

函數(shù)名字為:關(guān)鍵字operator后面接需要重載的運(yùn)算符符號(hào)。

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

需要注意的幾點(diǎn):

  1. 不能通過(guò)連接其他符號(hào)來(lái)創(chuàng)建新的操作符:比如operator@,必須是已有的操作符;
  2. 重載操作符必須有一個(gè)類類型或者枚舉類型的操作數(shù);
  3. 用于內(nèi)置類型的操作符,其含義不能改變,例如:內(nèi)置的整型+,不 能改變其含義;
  4. 作為類成員的重載函數(shù)時(shí),其形參看起來(lái)比操作數(shù)數(shù)目少1,成員函數(shù)的操作符有一個(gè)默認(rèn)的形參this,限定為第一個(gè)形參;
  5. 參數(shù)個(gè)數(shù)與重載的運(yùn)算符有關(guān);
  6. .* 、:: 、sizeof 、?: 、. 注意以上5個(gè)運(yùn)算符不能重載;
  7. 運(yùn)算符重載作用于左操作數(shù),會(huì)把左操作數(shù)當(dāng)做第一個(gè)參數(shù);

既然是對(duì)自定義類型對(duì)象之間的操作符的重載,那么它的參數(shù)一定有此類型的對(duì)象,并且需要對(duì)對(duì)象的成員進(jìn)行操作,這就需要打破封裝的限制,那么這個(gè)函數(shù)應(yīng)該設(shè)置為全局的還是類的成員呢?

有以下幾種思路:

  1. 函數(shù)設(shè)為公有,成員變量設(shè)為公有(不好);
  2. 函數(shù)設(shè)為公有另外寫(xiě)一個(gè)成員函數(shù)區(qū)獲取成員變量的值(不好);
  3. 將函數(shù)設(shè)為類的友元函數(shù)(可以);
  4. 放入類中,作為成員函數(shù)(推薦);
// 全局的operator==
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	int _year;
	int _month;
	int _day;
};
// 這里會(huì)發(fā)現(xiàn)運(yùn)算符重載成全局的就需要成員變量是共有的,那么問(wèn)題來(lái)了,封裝性如何保證?
// 這里其實(shí)可以用我們后面學(xué)習(xí)的友元解決,或者干脆重載成成員函數(shù)。
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year
	&& d1._month == d2._month
		&& d1._day == d2._day;
}
int main()
{
	Date d1(2018, 9, 26);
	Date d2(2018, 9, 29);
	cout << (d1 == d2) << endl;
	return 0;
}

這樣的寫(xiě)法就打破了封裝,讓類的成員都暴露了出來(lái),這樣的損失不太值得。

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

賦值操作運(yùn)算符重載特征如下:

  • 參數(shù)類型相同;
  • 返回值;
  • 檢測(cè)是否給自己賦值;
  • 返回*this;
  • 一個(gè)類如果沒(méi)有顯式的定義賦值操作符重載,編譯器會(huì)自動(dòng)生成一個(gè),完成對(duì)象字節(jié)序的拷貝(淺拷貝);
  • 賦值運(yùn)算符在類中不顯式實(shí)現(xiàn)時(shí),編譯器會(huì)生成一份默認(rèn)的,此時(shí)用戶在類外再將賦值運(yùn)算符重載為全局的,就和編譯器生成的默認(rèn)賦值運(yùn)算符沖突了,故賦值運(yùn)算符只能重載成成員函數(shù)。
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Display()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(2018, 10, 1);
	// 這里d1調(diào)用的編譯器生成operator=完成拷貝,d2和d1的值也是一樣的。
	d1 = d2;
	d1.Display();
	d2.Display();
	return 0;
}

是不是很像自動(dòng)生成的拷貝構(gòu)造?那么它也存在一定的問(wèn)題,對(duì)于日期類的對(duì)象他能很好的完成賦值操作,可對(duì)于指針類型呢?

下面的程序會(huì)崩潰

class String
{
public:
	String(const char* str = "songxin")
	{
		cout << "String(const char* str = \"songxin\")" << endl;
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	~String()
	{
		cout << "~String()" << endl;
		free(_str);
		_str = nullptr;
	}
private:
	char* _str;
};
int main()
{
	String s1("tanmei");
	String s2;
	s2 = s1;	
	return 0;
}

原因也是因?yàn)闇\拷貝的關(guān)系,導(dǎo)致同一塊內(nèi)存被釋放了兩次,程序崩潰。

可以不顯式定義賦值操作符重載函數(shù)的情況

  • 成員變量沒(méi)有指針;
  • 成員變量的指針沒(méi)有管理內(nèi)存資源;

注意:賦值操作符重載與拷貝構(gòu)造不同的地方就是拷貝構(gòu)造是在對(duì)象定義時(shí),而賦值操作符重載是作用于已經(jīng)存在的對(duì)象。

const成員

const修飾類的成員函數(shù),有點(diǎn)奇怪,const怎么能修飾函數(shù)呢?

將const修飾的類成員函數(shù)稱之為const成員函數(shù),const修飾類成員函數(shù),實(shí)際修飾該成員函數(shù)隱含的this指針指向的對(duì)象,表明在該成員函數(shù)中不能對(duì)指針指向?qū)ο蟮娜魏纬蓡T進(jìn)行修改。

class Date
{
public:
	Date()//構(gòu)造函數(shù)不寫(xiě)的話創(chuàng)建const的對(duì)象會(huì)報(bào)錯(cuò)。
		:
		_year(1900),
		_month(1),
		_day(1)
	{}
	void Display()
	{
		cout << "Display ()" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
	void Display() const
	{
		cout << "Display () 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;
	d1.Display();
	const Date d2;
	d2.Display();
	return 0;
}

const的對(duì)象就會(huì)調(diào)用Display函數(shù)會(huì)調(diào)用哪一個(gè)呢?注意到上面代碼的第18行的函數(shù)被const修飾,那么這個(gè)const有什么作用?

實(shí)際上這個(gè)const修飾的是*this,表明 *this不可被修改,那么const的對(duì)象就會(huì)調(diào)用被const修飾的函數(shù),否則可能會(huì)出現(xiàn)下面的問(wèn)題。

const對(duì)象可以調(diào)用非const成員函數(shù)嗎?

? 不可以,權(quán)限放大。

非const對(duì)象可以調(diào)用const成員函數(shù)嗎?

? 可以,權(quán)限縮小。

const成員函數(shù)內(nèi)可以調(diào)用其它的非const成員函數(shù)嗎?

? 不可以,權(quán)限放大。

非const成員函數(shù)內(nèi)可以調(diào)用其它的const成員函數(shù)嗎?

? 可以,權(quán)限縮小。

還有一個(gè)值得注意的地方,上面的代碼如果我們不顯式定義構(gòu)造函數(shù)的話,實(shí)例化const的對(duì)象時(shí)會(huì)報(bào)錯(cuò):

“d2”: 必須初始化 const 對(duì)象

也就是說(shuō)編譯器認(rèn)為const對(duì)象(包括成員)無(wú)法被賦值,應(yīng)該有初始化操作,而默認(rèn)生成的構(gòu)造是沒(méi)有對(duì)int有初始化操作的,因此報(bào)錯(cuò);

取地址及const取地址操作符重載

取地址操作符也要重載嗎?只有很少的情況會(huì)用到,通常直接使用編譯器默認(rèn)生成的就可以。

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

那么什么時(shí)候我們會(huì)重載呢?

  • 想讓別人獲取指定的內(nèi)容
  • 隱藏對(duì)象真實(shí)的地址
class Date
{
public:
	Date* operator&()//隱藏對(duì)象真實(shí)地址
	{
		return nullptr;
	}
	const int* operator&()const//讓用戶指定獲取成員變量_day的地址
	{
		return  &(_day);
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};
int main()
{
	const Date d1;
	Date d2;
	cout << &d1 << endl;//
	cout << &d2 << endl;//
	return 0;
}

輸出:

0000005597AFF770

0000000000000000

不過(guò)這樣的情況確實(shí)很少,也沒(méi)有什么意義。

到此這篇關(guān)于C++超詳細(xì)講解運(yùn)算符重載的文章就介紹到這了,更多相關(guān)C++運(yùn)算符重載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ push方法與push_back方法常見(jiàn)方法介紹

    C++ push方法與push_back方法常見(jiàn)方法介紹

    push與push_back是STL中常見(jiàn)的方法,都是向數(shù)據(jù)結(jié)構(gòu)中添加元素,本文還將簡(jiǎn)述push對(duì)應(yīng)的stack與queue系列,常見(jiàn)方法的介紹,以及與push_back相對(duì)應(yīng)的vector系列常見(jiàn)方法介紹,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • C++堆排序算法的實(shí)現(xiàn)方法

    C++堆排序算法的實(shí)現(xiàn)方法

    這篇文章主要介紹了C++堆排序算法的實(shí)現(xiàn)方法,很經(jīng)典的算法,需要的朋友可以參考下
    2014-08-08
  • C++超詳細(xì)講解RTTI和cast運(yùn)算符的使用

    C++超詳細(xì)講解RTTI和cast運(yùn)算符的使用

    RTTI(Runtime Type Identification)是“運(yùn)行時(shí)類型識(shí)別”的意思。C++引入這個(gè)機(jī)制是為了讓程序在運(yùn)行時(shí)能根據(jù)基類的指針或引用來(lái)獲得該指針或引用所指的對(duì)象的實(shí)際類型,cast強(qiáng)制轉(zhuǎn)換運(yùn)算符是一種特殊的運(yùn)算符,它把一種數(shù)據(jù)類型轉(zhuǎn)換為另一種數(shù)據(jù)類型
    2022-08-08
  • C++各種輸出數(shù)據(jù)類型詳解

    C++各種輸出數(shù)據(jù)類型詳解

    這篇文章主要介紹了C++各種輸出數(shù)據(jù)類型,在C++中,可以使用cout對(duì)象和插入運(yùn)算符<<輸出各種數(shù)據(jù)類型,包括整數(shù)類型、浮點(diǎn)數(shù)類型、字符類型、字符串類型和布爾類型,需要的朋友可以參考下
    2023-06-06
  • C語(yǔ)言中free函數(shù)的使用詳解

    C語(yǔ)言中free函數(shù)的使用詳解

    free函數(shù)是釋放之前某一次malloc函數(shù)申請(qǐng)的空間,而且只是釋放空間,并不改變指針的值。下面我們就來(lái)詳細(xì)探討下
    2017-05-05
  • C語(yǔ)言堆棧入門(mén)指南

    C語(yǔ)言堆棧入門(mén)指南

    我身邊的一些編程的朋友以及在網(wǎng)上看帖遇到的朋友中有好多也說(shuō)不清堆棧,所以我想有必要給大家分享一下我對(duì)堆棧的看法,有說(shuō)的不對(duì)的地方請(qǐng)朋友們不吝賜教,這對(duì)于大家學(xué)習(xí)會(huì)有很大幫助
    2014-01-01
  • C語(yǔ)言實(shí)現(xiàn)返回字符串函數(shù)的四種方法

    C語(yǔ)言實(shí)現(xiàn)返回字符串函數(shù)的四種方法

    在C語(yǔ)言中實(shí)現(xiàn)函數(shù)返回字符串,首先要確定函數(shù)返回的字符串地址的來(lái)源,一般分為四種方式,下面這篇文章就給大家通過(guò)示例代碼詳細(xì)介紹這幾種方法,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。
    2016-12-12
  • C語(yǔ)言修煉之路初識(shí)指針陰陽(yáng)竅?地址還歸大道真下篇

    C語(yǔ)言修煉之路初識(shí)指針陰陽(yáng)竅?地址還歸大道真下篇

    指針是指向另一個(gè)變量的變量。意思是一個(gè)指針保存的是另一個(gè)變量的內(nèi)存地址。換句話說(shuō),指針保存的并不是普通意義上的數(shù)值,而是另一個(gè)變量的地址值。一個(gè)指針保存了另一個(gè)變量的地址值,就說(shuō)這個(gè)指針“指向”了那個(gè)變量
    2022-02-02
  • C++11 lambda表達(dá)式在回調(diào)函數(shù)中的使用方式

    C++11 lambda表達(dá)式在回調(diào)函數(shù)中的使用方式

    這篇文章主要介紹了C++11 lambda表達(dá)式在回調(diào)函數(shù)中的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 如何通過(guò)C++在Bing搜索引擎上進(jìn)行命令行搜索

    如何通過(guò)C++在Bing搜索引擎上進(jìn)行命令行搜索

    這篇文章主要介紹了通過(guò)C++在Bing搜索引擎上進(jìn)行命令行搜索,在這篇文章中,我們將介紹一個(gè)簡(jiǎn)單的C++程序,允許用戶通過(guò)命令行輸入搜索詞,在Bing搜索引擎上執(zhí)行搜索,并在默認(rèn)瀏覽器中顯示搜索結(jié)果,需要的朋友可以參考下
    2023-12-12

最新評(píng)論