您好,登錄后才能下訂單哦!
本篇內容介紹了“C++運算符重載方法怎么使用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
C++為了增強代碼的可讀性引入了運算符重載,運算符重載是具有特殊函數名的函數,也具有其返回值類
型,函數名字以及參數列表,其返回值類型與參數列表與普通的函數類似。
函數名字為:關鍵字operator后面接需要重載的運算符符號。
函數原型:返回值類型 operator操作符(參數列表)
需要注意的幾點:
不能通過連接其他符號來創建新的操作符:比如operator@,必須是已有的操作符;
重載操作符必須有一個類類型或者枚舉類型的操作數;
用于內置類型的操作符,其含義不能改變,例如:內置的整型+,不 能改變其含義;
作為類成員的重載函數時,其形參看起來比操作數數目少1,成員函數的操作符有一個默認的形參this,限定為第一個形參;
參數個數與重載的運算符有關;
.* 、:: 、sizeof 、?: 、. 注意以上5個運算符不能重載;
運算符重載作用于左操作數,會把左操作數當做第一個參數;
既然是對自定義類型對象之間的操作符的重載,那么它的參數一定有此類型的對象,并且需要對對象的成員進行操作,這就需要打破封裝的限制,那么這個函數應該設置為全局的還是類的成員呢?
有以下幾種思路:
函數設為公有,成員變量設為公有(不好);
函數設為公有另外寫一個成員函數區獲取成員變量的值(不好);
將函數設為類的友元函數(可以);
放入類中,作為成員函數(推薦);
// 全局的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; }; // 這里會發現運算符重載成全局的就需要成員變量是共有的,那么問題來了,封裝性如何保證? // 這里其實可以用我們后面學習的友元解決,或者干脆重載成成員函數。 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;
一個類如果沒有顯式的定義賦值操作符重載,編譯器會自動生成一個,完成對象字節序的拷貝(淺拷貝);
賦值運算符在類中不顯式實現時,編譯器會生成一份默認的,此時用戶在類外再將賦值運算符重載為全局的,就和編譯器生成的默認賦值運算符沖突了,故賦值運算符只能重載成成員函數。
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修飾類成員函數,實際修飾該成員函數隱含的this指針指向的對象,表明在該成員函數中不能對指針指向對象的任何成員進行修改。
class Date { public: Date()//構造函數不寫的話創建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有初始化操作的,因此報錯;
取地址操作符也要重載嗎?只有很少的情況會用到,通常直接使用編譯器默認生成的就可以。
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++運算符重載方法怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。