15.C++-操作符重載

来源:https://www.cnblogs.com/lifexy/archive/2018/03/23/8635556.html
-Advertisement-
Play Games

首先回憶下以前學的函數重載 函數重載 函數重載的本質為相互獨立的不同函數 通過函數名和函數參數來確定函數調用 無法直接通過函數名得到重載函數的入口地址 函數重載必然發生在同一個作用域中 類中的函數重載 靜態成員函數能與普通成員函數建立重載關係 全局函數和成員函數不能構成重載關係 操作符重載(oper ...


首先回憶下以前學的函數重載

函數重載

  • 函數重載的本質為相互獨立的不同函數
  • 通過函數名函數參數來確定函數調用
  • 無法直接通過函數名得到重載函數的入口地址
  • 函數重載必然發生在同一個作用域

類中的函數重載

  • 靜態成員函數能與普通成員函數建立重載關係
  • 全局函數和成員函數不能構成重載關係

 

操作符重載(operator)

什麼是操作符重載?

大家都知道,在C里,有'+,-,*,/'這些操作符,且它們的功能就是實現普通變數運算。

由於C++是面向對象的,遇到的變數大多都是對象,所以優化了C里的操作符,使它們擁有了重載能力.能通過一定方式,使對象能進行'+,-,*,/'等運算.

操作符的重載是以函數的方式進行.

操作符重載定義

操作符重載,通過operator關鍵字在函數前定義:

[返回類型]  operator  [需要重載的操作符](函數參數)

{

       //......

}

 

操作符重載有幾種方式 : 全局操作符重載函數、全局操作符重載函數

編譯器首先會判斷運算的若是對象,就會先從類里尋找成員操作符重載函數,若沒找到,就會再去全局裡尋找全局操作符重載函數.

註意事項:

  • 操作符重載不能改變原操作符的優先順序
  • 操作符重載不能改變操作數的個數
  • 操作符重載的參數一般設為const class_name &類型(若只設為const class_name,會產生臨時對象)
  • 在C++中,有些操作符必須需要有對象支持,所以只能為成員函數.  比如賦值(=)、下標([])、調用(())和成員訪問箭頭(->):
Test t3=t2;   //相當於調用了: Test  t3.operator =(t2);  裡面會通過this指針來代替左側數t3
  • 有些操作符既可以當做成員操作符重載函數,也可以當做全局操作符重載函數,比如加法(+):

當設為全局操作符重載函數時,執行

Test t3=t1+t2;  //相當於調用了:  Test t3 = operator +(t1,t2); 

當設為成員操作符重載函數時,執行

Test t3=t1+t2;  //相當於調用了:  Test t3 =t1.operator +(t2);  //裡面會通過this指針來代替左側數t1

 

多個重載的操作符重載函數

由於操作符重載函數帶參數,所以可以存在多個相同的操作符重載函數

例如:

class Test
{

double  x;

double  y;

public:

Test operator +(const Test& t);                //實現Test t3=t1+t2

Test operator +(int i);                        //實現Test t3=t1+1

Test operator +(double d);                     //實現Test t3=t1+1.25

//... ...

};

  

 

初步試驗

1.接下來,來個全局操作符重載函數例子:

#include "stdio.h"


class Test{

       int x;
       int y;

public:
       Test(int x=0,int y=0)
       {
              this->x=x;
              this->y=y;     
       }
       int getx()
       {
              return x;
       }
       int gety()
       {
              return y;
       }

       friend Test operator + (const Test& t1,const Test& t2);
                                                 //聲明友元函數,可以使用私有成員變數     

};

Test operator + (const Test& t1,const Test& t2)              //重載
{
       Test ret;
       ret.x=t1.x+t2.x;
       ret.y=t1.y+t2.y;
       return ret;
}

int main()
{
       Test t1(1,3);
       Test t2(2,4);
       Test t3= t1 + t2;           // 其實就是調用: Test t3 = operator +(t1,t2);

       printf("t3.x:%d  t3.y:%d\n",t3.getx(),t3.gety());  

       Test t4 =operator +(t1,t3);   // t4 =t1 +t3

       printf("t4.x:%d  t4.y:%d\n",t4.getx(),t4.gety());

       return 0;
}

列印結果:

t3.x:3  t3.y:7
t4.x:4  t4.y:10

  

2.換成成員操作符重載函數例子:

#include "stdio.h"

class Test{

       int x;
       int y;

public:
       Test(int x=0,int y=0)
       {
         this->x =x;
         this->y =y;
       }

       int getx()
       {
              return x;
       }

       int gety()
       {
              return y;
       }   

    Test operator + (const Test& t2)
       {
              Test ret;

              ret.x = this->x + t2.x;
              ret.y = this->y + t2.y;
              return ret;
       }                                 
};

int main()
{
       Test t1(1,3);
       Test t2(2,4); 
       Test t3= t1 + t2;           // 其實就是調用: Test t3 =t1.operator +(t2);

       printf("t3.x:%d  t3.y:%d\n",t3.getx(),t3.gety());   

       Test t4 =t1.operator +(t3);   // t4 =t1 +t3

       printf("t4.x:%d  t4.y:%d\n",t4.getx(),t4.gety()); 

       return 0;
}

列印結果:

t3.x:3  t3.y:7
t4.x:4  t4.y:10

  

加深理解

由於C++里,沒有複數的慨念,而在剛剛又學習了操作符重載,所以接下來便通過操作符重載來實現複數類

複數類應該具有

兩個成員

實部a 、虛部b

運算操作符

+ - :  結果 = 兩個實部進行加減,兩個虛部進行加減

*   :  結果 = (a1+b1)(a2+b2)= (a1*a2 - b1*b2 )+( a2*b1 + a1*b2);

/   :  結果 =(a1+b1)/(a2+b2)= (a1*a2+b1*b2)/(a2* a2+b2* b2) +(b1*a2-a1*b2)/(a2* a2+b2* b2)

比較操作符:== ,!=

賦值操作符: =

求模成員函數 : 等於a^2+b^2的算術平方根

 

所以複數類的操作符重載共有以下幾個:

 

 

1.寫頭文件Complex.h:

#ifndef __COMPLEX_H
#define __COMPLEX_H

class Complex{

private:
       double a;
       double b;

public:
       Complex(int a=0,int b=0);
       Complex operator + (const Complex& t);
       Complex operator - (const Complex& t);
       Complex operator * (const Complex& t);
       Complex operator / (const Complex& t);
       bool operator == (const Complex& t);
       bool operator != (const Complex& t);
       Complex& operator = (const Complex& t);

       double getModulus();

       double getA();
       double getB();
};

#endif

 

2.寫源文件Complex.cpp

#include "Complex.h"
#include "math.h"

Complex::Complex(int a,int b)
{
       this->a = a;
       this->b = b;
}

Complex Complex::operator + (const Complex& t)
{
       Complex ret;   

       ret.a = a + t.a;
       ret.b = b + t.b;
       return ret;
}   

Complex Complex::operator - (const Complex& t)
{
       Complex ret;  

       ret.a = a - t.a;
       ret.b = b - t.b;
       return ret;
}

      

Complex Complex::operator * (const Complex& t)
{
       Complex ret;
       ret.a = (a* t.a - b* t.b );
       ret.b = (t.a *b + a* t.b );     
       return ret;
}

 

      

Complex Complex::operator / (const Complex& t)
{
       Complex ret;
       ret.a = (a* t.a + b* t.b)/(t.a * t.a + t.b * t.b);
       ret.b = (b* t.a - a* t.b)/(t.a * t.a + t.b * t.b);     
       return ret;
}

      

bool Complex::operator == (const Complex& t)
{
       if((a== t.a)&&(b== t.b))
        return true;

       else
        return false;
}     

bool Complex::operator != (const Complex& t)
{
       if((a!= t.a)||(b!= t.b))
        return true;

       else
        return false;
}

Complex& Complex::operator = (const Complex& t)
{
       if(this != &t)
       {
         a = t.a;
         b = t.b;
       }
       return *this;
}     

double Complex::getModulus()
{
       return sqrt( a*a + b*b);
}
     

double Complex::getA()
{
       return a;
}     

double Complex::getB()
{
       return b;
}     

 

3.寫測試文件test.cpp

#include "stdio.h"
#include "Complex.h"

int main()
{
       Complex t1(1,3);
       Complex t2(2,6);

       Complex t3=t1+t2;

       printf("t3.a=%f  t3.b=%f\n",t3.getA(),t3.getB());

       printf("t3 Modulus:%f\n",t3.getModulus());

       Complex t4=t3;

       printf("t4==t3: %d\n",t4==t3);
       printf("t4!=t3: %d\n",t4!=t3);
       printf("t3==t1: %d\n",t3==t1);

       return 0;
}

 

4.編譯運行

t3.a=3.000000  t3.b=9.000000
t3 Modulus:9.486833
t4==t3: 1                                   //為真
t4!=t3: 0                                   //為假
t3==t1: 0                                   //為假

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 設計模式(2) --簡單工廠模式 設計模式(3) --工廠方法模式 設計模式(4) --抽象工廠模式 設計模式之工廠模式 -- 簡單工廠、工廠、抽象工廠 ...
  • 1、創建mysql用戶賬號:groupadd mysqluseradd -d /sbin/nolog -g mysql -M mysql-s /sbin/nologin 表示禁止該用戶登錄,只需要角色存在即可,加強安全-g mysql 表示指定mysql用戶屬於mysql組-M 表示不創建用戶家目錄 ...
  • SpringBoot使用FastJson作為JSON格式轉換器的標準工具時,出現亂碼 ...
  • zookeeper簡單介紹及API使用 1.1 zookeeper簡介 zookeeper是一個針對大型分散式系統的可靠的協調系統,提供的功能包括配置維護、名字服務、分散式同步、組服務等。zookeeper可以集群複製,集群間通過zab協議來保持數據的一致性。該協議包括兩個階段:leader ele ...
  • 一、二叉樹就是這麼簡單 本文撇開一些非常苦澀、難以理解的概念來講講二叉樹,僅入門觀看(或複習).... 首先,我們來講講什麼是樹: 樹是一種 非線性 的數據結構,相對於線性的數據結構(鏈表、數組)而言, 樹的平均運行時間更短(往往與樹相關的排序時間複雜度都不會高) 在現實生活中,我們一般的樹長這個樣 ...
  • 本文內容: 抽象類 介面 抽象類與介面的異同 首發日期:2018-03-24 抽象類: 雖然已經有了父類,但有時候父類也是無法直接描述某些共有屬性的,比如哺乳類和人類都會叫,而一般來說哺乳類這個父類並沒有準確定義“叫”的屬性的,顯然應該由子類來決定怎麼“叫”,但“叫”這個屬性是共有的,那麼可以把這個 ...
  • Java long數據類型 位有符號的Java原始數據類型。當對整數的計算結果可能超出int數據類型的範圍時使用。 位有符號的Java原始數據類型。當對整數的計算結果可能超出int數據類型的範圍時使用。 long數據類型範圍是-9,223,372,036,854,775,808至9,223,372, ...
  • 從這篇文章開始,來記錄我的Django學習過程。 Day-1 一 首先是安裝Django版本的選擇,我所選擇的是Django1.11。為什麼選擇1.11呢,因為它是長期技術支持版(LTS),官方會加上新特性,和修複一些BUG。 好了,版本選擇好了,該安裝了,在我這兒安裝有兩種方法: 1. 打開CMD ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...