C++之運算符重載(上)

1、概念

所謂重載,就是重新賦予新的含義。函數重載就是對一個已有的函數賦予新的含義,使之實現新功能,因此,一個函數名就可以用來代表不同功能的函數,也就是”一名多用”。

運算符也可以重載。實際上,我們已經在不知不覺之中使用了運算符重載。例如,大 家都已習慣于用加法運算符”+”對整數、單精度數和雙精度數進行加法運算,如5+8, 5.8 +3.67等,其實計算機對整數、單精度數和雙精度數的加法操作過程是很不相同的, 但由于C++已經對運算符”+”進行了重載,所以就能適用于int, float, doUble類型的運算。

又如”<<“是C++的位運算中的位移運算符(左移),但在輸出操作中又是與流對 象cout 配合使用的流插入運算符,”>>“也是位移運算符(右移),但在輸入操作中又是與流對象 cin 配合使用的流提取運算符。這就是運算符重載(operator overloading)。C++系統對”<<“和”>>“進行了重載,用戶在不同的場合下使用它們時,作用是不同 的。對”<<“和”>>“的重載處理是放在頭文件stream中的。因此,如果要在程序中用”<< “和”>>”作流插入運算符和流提取運算符,必須在本文件模塊中包含頭文件stream(當然還應當包括”using namespace std“)。
現在要討論的問題是:用戶能否根據自己的需要對C++已提供的運算符進行重載,賦予它們新的含義,使之一名多用。

  • 運算符重載入門技術推演
    • 為什么會用運算符重載機制
      用復數類舉例
Complex c3 = c1 + c2; 

原因 Complex是用戶自定義類型,編譯器根本不知道如何進行加減.因此編譯器給提供了一種機制,讓用戶自己去完成,自定義類型的加減操作。這個機制就是運算符重載機制

  • 運算符重載的本質是一個函數
#include <stdio.h>// a + bi
class Complex
{friend Complex add (Complex &a, Complex &b);friend Complex operator+ (Complex &a, Complex &b);
public:Complex(){m_a = 0;m_b = 0;}Complex (int a, int b){m_a = a;m_b = b;}void print (){printf ("%d + %di\n", m_a, m_b);}Complex operator- (Complex &b){Complex tmp(m_a-b.m_a, m_b-b.m_b);return tmp;}private:int m_a;int m_b;
};// 全局函數
Complex add (Complex &a, Complex &b)
{Complex tmp(a.m_a+b.m_a, a.m_b+b.m_b);return tmp;
}// 運算符重載: 本質是一個函數
// 函數名字組成:operator + 要重載的運算符
Complex operator+ (Complex &a, Complex &b)
{Complex tmp(a.m_a+b.m_a, a.m_b+b.m_b);return tmp;
}// 運算符重載:給運算符重新定義功能
// 1、寫函數名:operator + 重載的運算符
// 2、根據運算需求  寫函數的 參數列表
// 3、根據需求 寫出函數返回值的類型 
int main()
{Complex c1(1,2), c2(3,4), c3, c4;c1.print();c2.print();// c3 = c1 + c2; // Complex 自定義的類,編譯器不知道以什么規則進行運算// c3 = add(c1, c2);// c3 = operator+(c1, c2);c3 = c1 + c2;  // ===> operator+(c1, c2);c3.print();// c4 = c3.operator-(c2);  // c3 - c2c4 = c3 - c2; // ====>  c4 = c3.operator-(c2)/operator-(c1, c2);// ( operator+(c1, c3) ).operator-(c2)c4 = c1 + c3 - c2;c4.print();return 0;
}int mai3_1()
{int a = 10, b= 20, c;c = a + b;    // 基礎的數據做運算,編譯器直到怎么做printf ("c = %d\n", c);return 0;
}

2、限制

這里寫圖片描述

3、基礎

這里寫圖片描述
例如:

//全局函數 完成 +操作符 重載
Complex operator+(Complex &c1, Complex &c2)
//類成員函數 完成 -操作符 重載
Complex operator-(Complex &c2)
  • 運算符重載的兩種方法
    這里寫圖片描述
    這里寫圖片描述

例如1:通過類成員函數完成-操作符重載

//函數聲明 Complex operator-(Complex &c2)
//函數調用分析
//用類成員函數實現-運算符重載Complex c4 = c1 - c2;c4.printCom();//c1.operator-(c2);

例如2:通過全局函數方法完成+操作符重載

//函數聲明 Complex operator+(Complex &c1, Complex &c2) 
//函數調用分析
int main()
{Complex c1(1, 2), c2(3, 4);//Complex c31 = operator+(c1, c2);
Complex c3 = c1 + c2; 
c3.printCom();
}

這里寫圖片描述
例如3

//前置++操作符 用全局函數實現 
Complex& operator++(Complex &c1) 
{c1.a ++;   c1.b ++;return c1;  
}
//調用方法 
++c1 ;               //需要寫出操作符重載函數原形 
c1.printCom();//運算符重載函數名定義 
//首先承認操作符重載是一個函數 定義函數名operator++ 
//分析函數參數 根據左右操作數的個數,operator++(Complex &c1) 
//分析函數返回值Complex& operator++(Complex &c1) 返回它自身

例如4

//4.1前置--操作符 成員函數實現
Complex& operator--()
{this->a--;this->b--;return *this;
}//4.2調用方法 
--c1; 
c1.printCom(); 
//4.3前置—運算符重載函數名定義 
//c1.operator–()

例如5

//5.1 //后置++ 操作符 用全局函數實現
Complex operator++(Complex &c1, int) 
{Complex tmp = c1;c1.a++;c1.b++;return tmp;
}//5.2 調用方法 
c1 ++ ; //先使用 后++ 
//5.3 后置++運算符重載函數名定義 
Complex operator++(Complex &c1, int)

函數占位參數 和 前置++ 相區別

例如6

//6.1 后置— 操作符 用類成員函數實現
Complex operator--(int) 
{Complex tmp = *this;this->a--;this->b--;return tmp;
}//6.2 調用方法 
c1 ++ ; //先使用 后++ 
//6.3 后置–運算符重載函數名定義 
Complex operator--(int) //函數占位參數 和 前置– 相區別

前置和后置運算符總結
C++中通過一個占位參數來區分前置運算和后置運算

#include <iostream>
using namespace std;class Complex
{
private:int a;int b;//全局函數 重載+運算符friend Complex operator+(Complex &c1, Complex &c2);//重載 前置++friend Complex& operator++(Complex &c1);friend Complex operator++(Complex &c1, int);
public:Complex(int a=0, int b=0){this->a = a;this->b = b;}void printCom(){cout<<a<<" + " << b << "i" <<endl;}
public://成員函數法 實現 -運算符重載Complex operator-(Complex &c2){Complex tmp(this->a - c2.a, this->b - c2.b);return tmp;}//前置--Complex& operator--(){this->a --;this->b --;return *this;}//后置--Complex operator--(int){Complex tmp = *this;this->a--;this->b--;return tmp;}
};//全局函數法 實現 + 運算符重載
Complex operator+(Complex &c1, Complex &c2)
{Complex tmp(c1.a + c2.a, c1.b + c2.b);return tmp;
}//前置++
Complex& operator++(Complex &c1)
{c1.a++;c1.b++;return c1;
}//后置++
Complex operator++(Complex &c1, int)
{//先使用 在讓c1加加Complex tmp = c1;//return c1;c1.a ++;c1.b ++;return tmp;
}/*
全局函數、類成員函數方法實現運算符重載步驟1)要承認操作符重載是一個函數,寫出函數名稱2)根據操作數,寫出函數參數 3)根據業務,完善函數返回值(看函數是返回引用 還是指針 元素),及實現函數業務
*/
void main()
{Complex c1(1, 2), c2(3, 4);//1 全局函數法 實現 + 運算符重載// Complex operator+(Complex &c1, Complex &c2);Complex c3 = c1 + c2;c3.printCom();//2 成員函數 法 實現 -運算符重載//c1.operator-(c2);//Complex operator-(Complex &c2)Complex c4 = c1 - c2;c4.printCom();//前置++操作符 用全局函數實現++c1;c1.printCom();//前置--操作符 成員函數方法--c1;c1.printCom();//Complex& operator++(Complex &c1)//c1.operator--();//后置++操作符 用全局函數實現c1++;c1.printCom();//后置--操作符 用成員函數實現c1--;c1.printCom();//c1.operator--()cout<<"hello..."<<endl;system("pause");return ;
}

友元函數實現操作符重載的應用場景
1) 友元函數和成員函數選擇方法

  • 當無法修改左操作數的類時,使用全局函數進行重載
  • =, [], ()和->操作符只能通過成員函數進行重載
    2)用友元函數重載<< >> 操作符
  • istream 和 ostream 是 C++ 的預定義流類
  • cin 是 istream 的對象,cout 是 ostream 的對象
  • 運算符 << 由ostream 重載為插入操作,用于輸出基本類型數據
  • 運算符 >> 由 istream 重載為提取操作,用于輸入基本類型數據
  • 用友員函數重載 << 和 >> ,輸出和輸入用戶自定義的數據類型

a)用全局函數方法實現<<操作符重載

ostream& operator<<(ostream &out, Complex &c1)
{//out<<"12345,生活真是苦"<<endl;out<<c1.a<<" + "<<c1.b<<"i "<<endl;return out;
}/調用方法 
cout<<c1; 
//鏈式編程支持 
cout<<c1<<"abcc"; 
//cout.operator<<(c1).operator<<("abcd"); 
/函數返回值充當左值 需要返回一個引用

b)類成員函數方法實現<<操作符重載

  • 因無法拿到cout這個類的源碼
  • cout.operator<<(c1);

友元函數重載操作符使用注意點
a)友元函數重載運算符常用于運算符的左右操作數類型不同的情況
這里寫圖片描述
b)其他

  • 在第一個參數需要隱式轉換的情形下,使用友員函數重載運算符是正確的選擇
  • 友員函數沒有 this 指針,所需操作數都必須在參數表顯式聲明,很容易實現類型的隱式轉換
  • C++中不能用友員函數重載的運算符有 = () [] ->

友元函數案例vector類

#include <iostream>
using namespace std;//為vector類重載流插入運算符和提取運算符 
class vector
{ 
public :vector( int size =1 ) ;       ~vector() ;int & operator[]( int i ) ;friend ostream & operator << ( ostream & output , vector & ) ;friend istream & operator >> ( istream & input, vector & ) ;
private :  int * v ;     int len ;
};vector::vector( int size ) 
{ if (size <= 0 || size > 100 ){ cout << "The size of " << size << " is null !\n" ; abort() ;  }v = new int[ size ] ;  len = size ;
}vector :: ~vector() 
{ delete[] v ;  len = 0 ; 
}int &vector::operator[]( int i )        
{ if( i >=0 && i < len )  return v[ i ] ;cout << "The subscript " << i << " is outside !\n" ;  abort() ;
}
ostream & operator << ( ostream & output, vector & ary )
{ for(int i = 0 ; i < ary.len ; i ++ )  output << ary[ i ] << "  " ;output << endl ;return output ;
}
istream & operator >> ( istream & input, vector & ary ) 
{ for( int i = 0 ; i < ary.len ; i ++ )  input >> ary[ i ] ;return  input ;
}void main()
{ int k ;cout << "Input the length of vector A :\n" ;     cin >> k ;vector A( k ) ;cout << "Input the elements of vector A :\n" ;     cin >> A ;cout << "Output the elements of vector A :\n" ;cout << A ;system("pause");
}

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

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

相關文章

手剎

定義 考手剎的專業稱呼是輔助制動器&#xff0c;與制動器的原理不同&#xff0c;其是采用鋼絲拉線連接到后制動蹄上&#xff0c;以對車子進行制動。作用 用于平地斜坡停車時制動&#xff0c;防止車子在無人狀態下自動滑跑&#xff0c;逼免發生交通事故。工作原理 其原…

關于[super dealloc]

銷毀一個對象時&#xff0c;需要重寫系統的dealloc方法來釋放當前類所擁有的對象&#xff0c;在dealloc方法中需要先釋放當前類中所有的對象&#xff0c;然后再調用[super dealloc]釋放父類中所擁有的對象。如先調用[super dealloc]將釋放掉父類中所擁有的對象&#xff0c;當前…

C++之運算符重載(下)

4.提高 1.運算符重載機制 編譯器實現運算符重載實際上就是通過函數重載實現的&#xff0c;可分為全局函數方式&#xff0c;也可分為成員函數方式進行重載&#xff0c;并沒有改變原操作符的屬性和語義。只是針對某個特定類定義一種新的數據類型操作。 2.重載賦值運算符 賦值…

Cookie / Session 的機制與安全

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Cookie和Session是為了在無狀態的HTTP協議之上維護會話狀態&#xff0c;使得服務器可以知道當前是和哪個客戶在打交道。本文來詳細討論C…

手動擋

定義 手動擋&#xff0c;即用手撥動變速桿才能改變變速器內的齒輪嚙合置&#xff0c;改變傳動比&#xff0c;從而達到變速的目的。作用 一方面提供了手動的樂趣 另外一方面就是通過手動自主控制轉速&#xff0c;還可以遲延或提前換檔。駕駛技巧 市區內應直視前方五…

Servlet快速入門及運行流程

一、Servlet快速入門 1.創建一個web工程 2.在JavaResource中src下創建一個包名稱為com.myxq.servlet 3.在創建的servlet包當中創建一個class文件起名為FirstServlet 4.進入該class實現一個Servlet接口&#xff0c;實現它未實現的方法 重點看service方法在該方法當中寫入一句話進…

C++之多繼承

1.基礎知識 1.1 類之間的關系 has-A&#xff0c;uses-A 和 is-A has-A 包含關系&#xff0c;用以描述一個類由多個“部件類”構成。實現has-A關系用類成員表示&#xff0c;即一個類中的數據成員是另一種已經定義的類。 常和構造函數初始化列表一起使用 uses-A 一個類部分地…

自動擋

定義 所謂自動擋&#xff0c;就是不用駕駛者去手動換檔&#xff0c;車輛會根據行駛的速度和交通情況自動選擇合適的檔位行駛。作用 能根據路面狀況自動變速&#xff0c;使駕駛者可以全神貫地注視路面交通而不會被換檔搞得手忙腳亂。工作原理 自動變速器&#xff0c…

聊一聊 cookie

我們看到的 cookie 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我自己創建了一個網站&#xff0c;網址為http://ppsc.sankuai.com。在這個網頁中我設置了幾個cookie&#xff1a;JS…

跨域資源共享 CORS 詳解

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 CORS是一個W3C標準&#xff0c;全稱是"跨域資源共享"&#xff08;Cross-origin resource sharing&#xff09;。 它允許瀏覽…

油門

定義 油門是內燃機上控制燃料供量的裝置。作用 是汽車發動機與摩托車油箱之間的閥門&#xff0c;控制汽油的量。操作注意 1.空車起步勿用大油門&#xff0c;以小油門為宜&#xff0c;負荷起步則以中油門為宜。 2.啟動時將油門放在合適位&#xff0c;使機件不易磨損。…

C++之泛型編程(模板)

1.模板綜述 背景 有時候許多函數或子程序的邏輯結構是一樣的&#xff0c;只是要處理的數據類型不一樣有時候多個類具有相同邏輯的成員函數和成員變量&#xff0c;只是成員變量的數據類型以及成員函數的參數類型不一樣模板就是解決數據類型不一致造成代碼冗余的一種機制&#xf…

Base64轉PDF、PDF轉IMG(使用pdfbox插件)

--添加依賴 <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox --><dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.12</version></dependency&…

const的用法,特別是用在函數后面

原文出處&#xff1a;http://blog.csdn.net/zcf1002797280/article/details/7816977

圖解 Linux 安裝 JDK1.8 、配置環境變量

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 到官網下載 JDK 1.8 https://www.oracle.com/technetwork/java/javase/downloads/index.html 2. 用 rz 命令把 jdk-8u191-linux-x6…

剎車

定義 剎車就是可以減慢車速的機械制動裝置&#xff0c;又名減速器。簡單來說&#xff0c;汽車剎車踏板在方向盤下面&#xff0c;踩住剎車踏板&#xff0c;則使剎車杠桿聯動受壓并傳至到剎車鼓上的剎車片卡住剎車輪盤&#xff0c;使汽車減速或停止運行。作用 目的是減速&a…

【原創】Performanced C++ 經驗規則 第五條:再談重載、覆蓋和隱藏

第五條&#xff1a;再談重載、覆蓋和隱藏 在C中&#xff0c;無論在類作用域內還是外&#xff0c;兩個&#xff08;或多個&#xff09;同名的函數&#xff0c;可能且僅可能是以下三種關系&#xff1a;重載&#xff08;Overload&#xff09;、覆蓋&#xff08;Override&#xff0…

C++之純虛函數和抽象類

純虛函數和抽象類 1.基本概念 2.案例 #include <iostream> using namespace std;////面向抽象類編程(面向一套預先定義好的接口編程)//解耦合 ....模塊的劃分class Figure //抽象類 { public://閱讀一個統一的界面(接口),讓子類使用,讓子類必須去實現virtual void get…

解決: -bash: $‘\302\240docker‘: command not found

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我只是運行 一條很簡單的啟動容器的命令&#xff0c;多次執行都報錯&#xff0c;報錯如題&#xff1a; -bash: $\302\240docker: comma…

換擋/掛檔

定義 換擋/掛檔是指變速器&#xff0c;用于轉變發動機曲軸的轉矩及轉速&#xff0c;以適應汽車在起步、加速、行駛以及克服各種道路阻礙等不同行駛條件下對驅動車輪牽引力及車速不同要求的需要。作用 使汽車能以非常低的穩定車速行駛&#xff0c;而這種低的轉速只靠內然…