【C++學習筆記四】運算符重載

當調用一個重載函數和重載運算符時,編譯器通過把您所使用的參數類型和定義中的參數類型相比較,巨鼎選用最合適的定義。(重載決策)

重載運算符時帶有特殊名稱的函數,函數名是由關鍵字operator和其后要重載的運算符符號構成,與其他函數一樣,重載運算符有一個返回類型和一個參數列表。

返回類型 operator 運算符(參數列表)
{...
}

大多數的重載運算符可被定義為不同的非成員函數,或者定義為類成員函數。

不可重載的運算符:

  • .成員訪問運算符
  • .* ->*成員指針訪問運算符
  • ::域運算符
  • ?:條件運算符
  • #預處理符號
輸入輸出運算符重載

首先我們需要對流輸入輸出的原理有一個簡單的理解。
cinistream類的對象,coutostream類的對象
cin>>x; 相當于cin.operator>>x;然后會在輸入緩沖區中讀入整型數據后返回流輸入對象cin,方便以后再次輸入。

我們可以傳統的寫法進行運算符重載:

例如:

#include <iostream>
using namespace std;class Distance
{
private:int feet;             // 0 到無窮int inches;           // 0 到 12
public:// 所需的構造函數Distance() {feet = 0;inches = 0;}Distance(int f, int i) {feet = f;inches = i;}ostream& operator<<(ostream& os){os << "英寸:" << feet << "\n英尺:" << inches;return os;}
};
int main()
{Distance d1(20, 18);d1 << cout << endl<< "成功"<< endl;//相當于d1.operator<<(cout)
}

運行結果:

在這里插入圖片描述
這樣寫雖然可以但是不太符合我們的習慣,我們更習慣將cout放到最左邊。為了能夠適用這種寫法,我們需要使用友元函數。

詳見代碼:

#include <iostream>
using namespace std;class Distance
{
private:int feet;             // 0 到無窮int inches;           // 0 到 12
public:// 所需的構造函數Distance() {feet = 0;inches = 0;}Distance(int f, int i) {feet = f;inches = i;}friend ostream& operator<<(ostream& os,const Distance& x){os << "英寸:" << x.feet << "\n英尺:" << x.inches;return os;}
};
int main()
{Distance d1(20, 18);cout<< d1 << endl<< "成功"<< endl;//相當于d1.operator<<(cout)
}

這樣寫起來就顯得很自然。這里我們通過友元函數進行重載。因為<<是二元操作符的緣故我們需要兩個參數。其他操作符也可以使用友元函數進行重載,只需要將操作對象放到參數列表中即可。

自增自減運算符的重載

因為自增自減運算符有前綴和后綴之分,因此在重載時也有所不同。除去實現上的不同,后綴運算符在重載的時候參數列表需要有一個int,來向編譯器說明這是一個后綴形式 。例如:

返回類型 operator++ (int)
{}

自增和自減運算符一般是改變對象的狀態,所以一般是重載為成員函數。

在實際實現的時候,對于前綴運算符我們直接改變成員的狀態然后返回一個相同的成員。對于后綴運算符我們先創建一個對象保存對象的值,然后進行改變,最后返回原來的值。

例如:


#include <iostream>
using namespace std;class Time
{private:int hours;             // 0 到 23int minutes;           // 0 到 59public:// 所需的構造函數Time(){hours = 0;minutes = 0;}Time(int h, int m){hours = h;minutes = m;}// 顯示時間的方法void displayTime(){cout << "H: " << hours << " M:" << minutes <<endl;}// 重載前綴遞增運算符( ++ )Time operator++ ()  {++minutes;          // 對象加 1if(minutes >= 60)  {++hours;minutes -= 60;}return Time(hours, minutes);}// 重載后綴遞增運算符( ++ )Time operator++( int )         {// 保存原始值Time T(hours, minutes);// 對象加 1++minutes;                    if(minutes >= 60){++hours;minutes -= 60;}// 返回舊的原始值return T; }
};
int main()
{Time T1(11, 59), T2(10,40);++T1;                    // T1 加 1T1.displayTime();        // 顯示 T1++T1;                    // T1 再加 1T1.displayTime();        // 顯示 T1T2++;                    // T2 加 1T2.displayTime();        // 顯示 T2T2++;                    // T2 再加 1T2.displayTime();        // 顯示 T2return 0;
}
賦值運算符重載

詳見實例:

#include <iostream>
using namespace std;class Distance
{private:int feet;             // 0 到無窮int inches;           // 0 到 12public:// 所需的構造函數Distance(){feet = 0;inches = 0;}Distance(int f, int i){feet = f;inches = i;}void operator=(const Distance &D ){ feet = D.feet;inches = D.inches;}// 顯示距離的方法void displayDistance(){cout << "F: " << feet <<  " I:" <<  inches << endl;}};
int main()
{Distance D1(11, 10), D2(5, 11);cout << "First Distance : "; D1.displayDistance();cout << "Second Distance :"; D2.displayDistance();// 使用賦值運算符D1 = D2;cout << "First Distance :"; D1.displayDistance();return 0;
}
函數調用運算符()重載

重載函數的參數列表就是()應該加上的內容

#include <iostream>
using namespace std;class Distance
{private:int feet;             // 0 到無窮int inches;           // 0 到 12public:// 所需的構造函數Distance(){feet = 0;inches = 0;}Distance(int f, int i){feet = f;inches = i;}// 重載函數調用運算符Distance operator()(int a, int b, int c){Distance D;// 進行隨機計算D.feet = a + c + 10;D.inches = b + c + 100 ;return D;}// 顯示距離的方法void displayDistance(){cout << "F: " << feet <<  " I:" <<  inches << endl;}};
int main()
{Distance D1(11, 10), D2;cout << "First Distance : "; D1.displayDistance();D2 = D1(10, 10, 10); // invoke operator()cout << "Second Distance :"; D2.displayDistance();return 0;
}
下標運算符[]重載

同樣的,重載函數的參數列表應該和[]中的內容相同。

類成員訪問運算符->重載

成員訪問運算符可以被重載,只是比較麻煩。它被定義為為一個類賦予指針行為。

  • ->必須是一個成員函數
  • 返回類型必須是指針或者類的對象

類成員訪問運算符->通常與指針引用運算符*結合使用。用于實現“智能指針”的功能。這些指針可以自動執行一些操作,如在刪除指針的時候同時析構對象等來防止一些內存泄漏的問題。

想要了解更多可以參見:傳送門

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383798.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383798.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383798.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++11新特性】 C++11智能指針之unique_ptr

原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50759210 在前面一篇文章中&#xff0c;我們了解了C11中引入的智能指針之一shared_ptr&#xff0c;今天&#xff0c;我們來介紹一下另一種智能指針unique_ptr。 unique_ptr介紹 uni…

C++派生類對象和基類對象賦值

在C中&#xff0c;我們允許 將派生類對象賦給基類對象。&#xff08;不允許將基類對象賦給派生類對象&#xff09; 只會將基類對象成員賦值用基類指針指向派生類對象。&#xff08;不允許用派生類指針指向基類對象&#xff09; 基類指針只能操作基類中的成員基類引用作為派生類…

【C++11新特性】 C++11智能指針之shared_ptr

http://blog.csdn.net/Xiejingfa/article/details/50750037 原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50750037 C中的智能指針首先出現在“準”標準庫boost中。隨著使用的人越來越多&#xff0c;為了讓開發人員更方便、更安…

C++(純)虛函數重寫時訪問權限更改問題

我們知道在Java中是自動實現多態的&#xff0c;Java中規定重寫的方法的訪問權限不能縮小。那么在C中我們實現多態的時候是否可以更改&#xff08;縮小&#xff09;訪問權限呢&#xff1f; 經過測試&#xff0c;得到的答案如下&#xff1a;如果用基類指針指向派生類對象實現多態…

C++ — 智能指針的簡單實現以及循環引用問題

http://blog.csdn.net/dawn_sf/article/details/70168930 智能指針 ____________________________________________________ 今天我們來看一個高大上的東西&#xff0c;它叫智能指針。 哇這個名字聽起來都智能的不得了&#xff0c;其實等你了解它你一定會有一點失望的。。。。因…

C++(靜態)(常量)數據進行初始化問題以及靜態變量析構

在C11標準以前我們都不可以在類中對數據成員初始化&#xff0c;僅能在構造函數中進行初始化&#xff1a; class A {int a,b; double c; string d;A():a(1),b(2),c(3),d(""){} };在C11標準以后我們可以在類中對非靜態成員進行初始化。實際上的機制是在調用構造函數的…

C++this指針的用法

參考博客&#xff1a;https://www.cnblogs.com/zhengfa-af/p/8082959.html 在 訪問對象的非靜態成員時會隱式傳遞一個參數&#xff0c;即對象本身的指針&#xff0c;這個指針名為this。 例如&#xff1a; class A {int a1;public:A(){}void GetA(int a){cout<<this-&g…

C++開發者都應該使用的10個C++11特性

http://blog.jobbole.com/44015/ 感謝馮上&#xff08;治不好你我就不是獸醫 &#xff09;的熱心翻譯。如果其他朋友也有不錯的原創或譯文&#xff0c;可以嘗試推薦給伯樂在線。】 在C11新標準中&#xff0c;語言本身和標準庫都增加了很多新內容&#xff0c;本文只涉及了一些皮…

C++不能被聲明為虛函數

虛函數是為了實現多態&#xff0c;但是顯然并不是所有函數都可以聲明為虛函數的。 不能被聲明為虛函數的函數有兩類&#xff1a; 不能被繼承的函數不能被重寫的函數 因此&#xff0c;這些函數都不能被聲明為虛函數 普通函數構造函數 如果構造函數定義為虛函數&#xff0c;則…

類的聲明與定義

類的前向聲明&#xff1a; class A;在聲明之后&#xff0c;定義之前&#xff0c;類A是一個不完全類型&#xff0c;即知道A是一個類&#xff0c;但是不知道包含哪些成員。不完全類型只能以有限方式使用&#xff0c;不能定義該類型的對象&#xff0c;不完全類型只能用于定義指向…

shared_ptr的一些尷尬

http://blog.csdn.net/henan_lujun/article/details/8984543 shared_ptr在boost庫中已經有多年了&#xff0c;C11又為其正名&#xff0c;把他引入了STL庫&#xff0c;放到了std的下面&#xff0c;可見其頗有用武之地&#xff1b;但是shared_ptr是萬能的嗎&#xff1f;有沒有什…

C++轉換構造函數和類型轉換函數

參考博客&#xff1a;https://blog.csdn.net/feiyanaffection/article/details/79183340 隱式類型轉換 如果不同類型的數據在一起操作的時候編譯器會自動進行一個數據類型轉換。例如常用的基本數據類型有如下類型轉換關系&#xff1a; 轉換構造函數 構造函數有且僅有一個參數…

C++總結8——shared_ptr和weak_ptr智能指針

http://blog.csdn.net/wendy_keeping/article/details/75268687 智能指針的提出&#xff1a;智能指針是存儲指向動態分配對象指針的類&#xff0c;用于生存期控制。能夠確保正確銷毀動態分配的內存&#xff0c;防止內存泄露。 1.智能指針的分類&#xff1a; 不帶引用計數的智能…

C++析構函數執行順序

今天發現主程序中有多個對象時析構函數的執行順序不是對象定義的順序&#xff0c;而是對象定義順序反過來。 思考了一下&#xff0c;結合之前繼承、成員對象等的析構函數執行的順序&#xff0c;我覺得析構函數執行的順序為&#xff1a;構造函數的順序反過來&#xff0c;可能是…

c++寫時拷貝1

http://blog.csdn.net/SuLiJuan66/article/details/48882303 Copy On Write Copy On Write(寫時復制)使用了“引用計數”&#xff08;reference counting&#xff09;&#xff0c;會有一個變量用于保存引用的數量。當第一個類構造時&#xff0c;string的構造函數會根據傳入的參…

【C++學習筆記五】模板

模板是泛型編程的基礎 函數模板 模板定義以關鍵字template開始&#xff0c;后跟一個模板參數列表。這是一個逗號分隔的一個或多個模板參數的列表。用尖括號包圍起來。 模板函數定義的一般形式&#xff1a; template <class type> ret-tye func-name(parameter list) …

【Java學習筆記十】輸入輸出流

在Java.io包中提供了一系列用于處理輸入/輸出的流類。從功能上分為兩類&#xff1a;輸入流和輸出流。從六結構上可分為&#xff1a;字節流&#xff08;以字節為處理單位&#xff09;和字符流&#xff08;以字符為處理單位&#xff09;。 字符是由字節組成。在Java中所有字符用…

C++ 寫時拷貝 2

什么情況下會用到c中的拷貝構造函數】&#xff1a; 1&#xff09;用已經存在的同類的對象去構造出另一個新的對象 2&#xff09;當函數的形參是類的對象時&#xff0c;這時調用此函數&#xff0c;使用的是值的拷貝&#xff0c;也會調用拷貝構造函數 3&#xff09;當函數的返…

【Java學習筆記十一】圖形用戶界面

圖形用戶界面或圖形用戶接口(Graphical User Interface&#xff0c;GUI)是指采用圖形方式,借助菜單、按鈕等標準界面元素&#xff0c;用戶可以通過鼠標等外設向計算機系統發出指令、啟動操作&#xff0c;并將系統運行的結果同樣以圖形方式顯示給用戶的技術。 GUI是事件驅動的&…

C++ 寫時拷貝 3

http://blog.csdn.net/ljianhui/article/details/22895505 字符串一種在程序中經常要使用到的數據結構&#xff0c;然而在C中卻沒有字符串這種類型。在C中&#xff0c;為了方便字符串的使用&#xff0c;在STL中提供了一個string類。該類維護一個char指針&#xff0c;并封裝和提…