最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++超詳細講解運算符重載

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

概念

C++為了增強代碼的可讀性引入了運算符重載,運算符重載是具有特殊函數名的函數,也具有其返回值類

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

函數名字為:關鍵字operator后面接需要重載的運算符符號。

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

需要注意的幾點:

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

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

有以下幾種思路:

  1. 函數設為公有,成員變量設為公有(不好);
  2. 函數設為公有另外寫一個成員函數區(qū)獲取成員變量的值(不好);
  3. 將函數設為類的友元函數(可以);
  4. 放入類中,作為成員函數(推薦);
// 全局的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;
};
// 這里會發(fā)現運算符重載成全局的就需要成員變量是共有的,那么問題來了,封裝性如何保證?
// 這里其實可以用我們后面學習的友元解決,或者干脆重載成成員函數。
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;
}

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

賦值運算符重載

賦值操作運算符重載特征如下:

  • 參數類型相同;
  • 返回值;
  • 檢測是否給自己賦值;
  • 返回*this;
  • 一個類如果沒有顯式的定義賦值操作符重載,編譯器會自動生成一個,完成對象字節(jié)序的拷貝(淺拷貝);
  • 賦值運算符在類中不顯式實現時,編譯器會生成一份默認的,此時用戶在類外再將賦值運算符重載為全局的,就和編譯器生成的默認賦值運算符沖突了,故賦值運算符只能重載成成員函數。
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調用的編譯器生成operator=完成拷貝,d2和d1的值也是一樣的。
	d1 = d2;
	d1.Display();
	d2.Display();
	return 0;
}

是不是很像自動生成的拷貝構造?那么它也存在一定的問題,對于日期類的對象他能很好的完成賦值操作,可對于指針類型呢?

下面的程序會崩潰

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;
}

原因也是因為淺拷貝的關系,導致同一塊內存被釋放了兩次,程序崩潰。

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

  • 成員變量沒有指針;
  • 成員變量的指針沒有管理內存資源;

注意:賦值操作符重載與拷貝構造不同的地方就是拷貝構造是在對象定義時,而賦值操作符重載是作用于已經存在的對象。

const成員

const修飾類的成員函數,有點奇怪,const怎么能修飾函數呢?

將const修飾的類成員函數稱之為const成員函數,const修飾類成員函數,實際修飾該成員函數隱含的this指針指向的對象,表明在該成員函數中不能對指針指向對象的任何成員進行修改。

class Date
{
public:
	Date()//構造函數不寫的話創(chuàng)建const的對象會報錯。
		:
		_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的對象就會調用Display函數會調用哪一個呢?注意到上面代碼的第18行的函數被const修飾,那么這個const有什么作用?

實際上這個const修飾的是*this,表明 *this不可被修改,那么const的對象就會調用被const修飾的函數,否則可能會出現下面的問題。

const對象可以調用非const成員函數嗎?

? 不可以,權限放大。

非const對象可以調用const成員函數嗎?

? 可以,權限縮小。

const成員函數內可以調用其它的非const成員函數嗎?

? 不可以,權限放大。

非const成員函數內可以調用其它的const成員函數嗎?

? 可以,權限縮小。

還有一個值得注意的地方,上面的代碼如果我們不顯式定義構造函數的話,實例化const的對象時會報錯:

“d2”: 必須初始化 const 對象

也就是說編譯器認為const對象(包括成員)無法被賦值,應該有初始化操作,而默認生成的構造是沒有對int有初始化操作的,因此報錯;

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

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

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

那么什么時候我們會重載呢?

  • 想讓別人獲取指定的內容
  • 隱藏對象真實的地址
class Date
{
public:
	Date* operator&()//隱藏對象真實地址
	{
		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

不過這樣的情況確實很少,也沒有什么意義。

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

相關文章

  • C++實現簡單職工信息管理系統(tǒng)

    C++實現簡單職工信息管理系統(tǒng)

    本文給大家分享的是使用C++實現簡單的職工信息管理系統(tǒng)的代碼,本系統(tǒng)采用了面向對象的程序設計方法,所有的方法均以類為基礎,感興趣的小伙伴們可以參考一下
    2015-08-08
  • C/C++后端學習與練習深入

    C/C++后端學習與練習深入

    這篇文章主要介紹了C/C++對于后端的學習與練習,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • C++:string字符串的切片方式

    C++:string字符串的切片方式

    這篇文章主要介紹了C++:string字符串的切片方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 詳解C語言中telldir()函數和seekdir()函數的用法

    詳解C語言中telldir()函數和seekdir()函數的用法

    這篇文章主要介紹了詳解C語言中telldir()函數和seekdir()函數的用法,是C語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-09-09
  • C++二叉樹實現詞頻分析功能

    C++二叉樹實現詞頻分析功能

    這篇文章主要為大家詳細介紹了C++二叉樹實現詞頻分析功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • C++如何動態(tài)的生成對象詳解

    C++如何動態(tài)的生成對象詳解

    C++是不支持根據類名動態(tài)地生成對象的,比如從一個文本文件中讀取類名然后構造一個對象.主要原因是沒有豐富的動態(tài)元信息,沒有單根類庫。那么下面這篇文章就來給大家介紹C++是如何動態(tài)的生成對象,有需要的朋友們可以參考借鑒。
    2017-02-02
  • C/C++中typedef的用法大全

    C/C++中typedef的用法大全

    typedef用法一共七種,分別是:為基本數據類型起別名、為結構體起別名、為指針類型起別名、為數組類型起別名、為枚舉類型起別名、為模版函數起別名。本文就來分別講講這7個用法的具體實現吧
    2023-04-04
  • C++中vector操作方式詳解(多種方式)

    C++中vector操作方式詳解(多種方式)

    這篇文章主要介紹了C++中vector操作方式詳解(多種方式),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • C語言數據結構之線性表的鏈式存儲結構

    C語言數據結構之線性表的鏈式存儲結構

    線性表是最基本、最簡單、也是最常用的一種數據結構。線性表(linear list)是數據結構的一種,一個線性表是n個具有相同特性的數據元素的有限序列,這篇文章帶你學習下線性表的鏈式存儲結構
    2021-11-11
  • C語言中冒泡排序算法詳解

    C語言中冒泡排序算法詳解

    大家好,本篇文章主要講的是C語言中冒泡排序算法詳解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01

最新評論

通化县| 乐至县| 梨树县| 高邑县| 宁国市| 和平县| 安丘市| 隆德县| 佛坪县| 西林县| 千阳县| 漯河市| 蛟河市| 山西省| 任丘市| 谢通门县| 禄丰县| 嵊州市| 广宗县| 南漳县| 东光县| 泰和县| 昂仁县| 沧州市| 合川市| 襄城县| 蓬莱市| 夏河县| 来凤县| 台中县| 泌阳县| 邻水| 汕尾市| 霞浦县| 江华| 施秉县| 浑源县| 封丘县| 海盐县| 观塘区| 甘孜县|