最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

9.C++運(yùn)算符重載

2022-12-04 20:42 作者:限量版范兒  | 我要投稿

運(yùn)算符重載

本文包括了對C++類的6個默認(rèn)成員函數(shù)中的賦值運(yùn)算符重載和取地址和const對象取地址操作符的重載。

運(yùn)算符是程序中最最常見的操作,例如對于內(nèi)置類型的賦值我們直接使用=賦值即可,因為這些編譯器已經(jīng)幫我們做好了,但是對象的賦值呢?能直接賦值嗎?

概念

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

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

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

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

  • 不能通過連接其他符號來創(chuàng)建新的操作符:比如operator@,必須是已有的操作符;

  • 重載操作符必須有一個類類型或者枚舉類型的操作數(shù);

  • 用于內(nèi)置類型的操作符,其含義不能改變,例如:內(nèi)置的整型+,不 能改變其含義;

  • 作為類成員的重載函數(shù)時,其形參看起來比操作數(shù)數(shù)目少1,成員函數(shù)的操作符有一個默認(rèn)的形參this,限定為第一個形參;

  • 參數(shù)個數(shù)與重載的運(yùn)算符有關(guān);

  • .* 、:: 、sizeof 、?: 、. 注意以上5個運(yùn)算符不能重載;

  • 運(yùn)算符重載作用于左操作數(shù),會把左操作數(shù)當(dāng)做第一個參數(shù);

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

有以下幾種思路

  1. 函數(shù)設(shè)為公有,成員變量設(shè)為公有(不好);

  2. 函數(shù)設(shè)為公有另外寫一個成員函數(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; }; // 這里會發(fā)現(xiàn)運(yùn)算符重載成全局的就需要成員變量是共有的,那么問題來了,封裝性如何保證? // 這里其實可以用我們后面學(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; }

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

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

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

  • 參數(shù)類型相同;

  • 返回值;

  • 檢測是否給自己賦值;

  • 返回*this;

  • 一個類如果沒有顯式的定義賦值操作符重載,編譯器會自動生成一個,完成對象字節(jié)序的拷貝(淺拷貝);

  • 賦值運(yùn)算符在類中不顯式實現(xiàn)時,編譯器會生成一份默認(rèn)的,此時用戶在類外再將賦值運(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; }

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

下面的程序會崩潰

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

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

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

  • 成員變量沒有指針;

  • 成員變量有指針,但是指針沒有管理內(nèi)存資源;

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

const成員

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

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

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

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

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

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

  • 非const對象可以調(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òu)造函數(shù)的話,實例化const的對象時會報錯

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

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

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

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

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

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

  • 想讓別人獲取指定的內(nèi)容的地址;

  • 隱藏對象真實的地址;

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

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

文章標(biāo)題:9.C++運(yùn)算符重載
文章鏈接:https://www.dianjilingqu.com/628683.html

9.C++運(yùn)算符重載的評論 (共 條)

分享到微博請遵守國家法律
林州市| 保亭| 永平县| 万州区| 沽源县| 永年县| 长泰县| 军事| 自贡市| 鄱阳县| 鹤庆县| 云龙县| 金平| 长宁县| 永仁县| 资溪县| 宜宾市| 南川市| 开化县| 大丰市| 沙坪坝区| 宜丰县| 武平县| 邹城市| 巴林左旗| 砀山县| 岳普湖县| 阿瓦提县| 嘉祥县| 大厂| 大埔县| 杭锦后旗| 阜新| 婺源县| 华宁县| 平潭县| 海晏县| 凤台县| 永春县| 海阳市| 紫云|