運算符重載(輸入輸出流運算符重載實例)

C++運算符_菜鳥教程

C++內置了多種運算符,支持基本數據類型運算,其中的部分運算符已針對不同操作數類型進行了重載
將這些運算符用於自定義類型時,可進行運算符重載

運算符重載只是一種 “ 語法上的方便 ” ,也就是說這是另一種函數調用方式

基本語法

定義重載的運算符(可視爲特殊函數)就像定義(全局或類的成員)函數一樣,有一個小小的區別是函數的名稱:

operator@

其中operator是關鍵字,@是被重載的運算符,如:

HugeInt operator+(const HugeInt &A);

重載運算符的限制

  • 並不是所有的運算符都支持重載:

在這裏插入圖片描述
簡單解釋一下->*.*

class Fred{...};

typedef int (Fred::*FredMemFn)(int i, double d);  
// use a typedef!!! please!!!

void sample(Fred x, Fred& y, Fred* z, FredMemFn func)
{
    x.*func(42, 3.14);
    y.*func(42, 3.14);
    z->*func(42, 3.14);
}
typedef char (*PTRFUN)(int); 
PTRFUN pFun; 
char glFun(int a){ return;} 
void main() 
{ 
    pFun = glFun; 
    (*pFun)(2); 
} 

解釋:
typedef的功能是定義新的類型。
第一句定義了一種PTRFUN類型,並定義這種類型爲指向某種函數的指針,該函數以一個int爲參數並返回char類型。後面就可以像使用int或char一樣使用PTRFUN了。
第二行的代碼便使用這個新類型定義了變量pFun,此時就可以像使用形式1一樣使用這個變量了。

一般情況下,這三個運算符沒有重載的必要:

= 賦值運算符
& 取地址運算符
, 逗號運算符
  • 重載運算符不能改變原先默認的運算符優先級,結合律和操作數數目
  • 僅能重載現有運算符,不能創造新運算符
  • 僅能重載應用於自定義數據類型操作數的運算符
    我可以重載作用於HugeInt + HugeInt,HugeInt + int+,但是不能重載作用於int + int+

定義方式

  • 非靜態的類成員函數
class Data{
public:
    bool operator!() const;
};
  • 全局函數
    • friend:未訪問私有數據成員或私有成員函數
    • non-friend: 訪問了私有數據成員或私有成員函數
class PhoneNumber{
    friend ostream &operator<<(ostream&,const PhoneNumber&);
};

調用方式

普通函數

  • 全局函數:函數名(參數列表)
  • 類成員函數:多數情況下,對象.函數名(參數列表)

重載運算符

  • 使用時以表達式形式出現,例:HugeIntA+ HugeIntB

這裏就不得不提示一下:

  • HugeIntA + intA
    遇到這樣的表達式,編譯器會從兩種重載函數調用形式中二選一(也就是程序員必須提供兩者之一的重載運算符)

HugeIntA.operator+(int);

class HugeInt{
public:
    HugeInt operator+(int);
};

operator+(HugeIntA,intA);

class HugeInt{
    friend HugeInt operator+(const HugeInt&,int);
};
  • intB+ HugeIntB
    遇到這樣的表達式,編譯器只承認一種重載函數調用形式

int.operator+(HugeInt B);
非法,編譯失敗CE

operator+(intB,HugeIntB);

class HugeInt{
    friend HugeInt operator+(int,const HugeInt&);
};

設計原則

  • (),[],->和賦值運算符=,+=,-=必須重載爲成員函數
  • >>,<<和需要支持交換律的運算符最好重載爲全局函數
  • 其餘運算符可以重載爲成員函數,也可以重載爲全局函數
  • 當重載爲類的成員函數時
    • 自動包含該類對象(或其引用)作爲操作數,因此函數參數個數等於運算符目數-1
    • 左操作數(或唯一的操作數必須是該類對象(或對象引用)
  • 當重載爲全局函數時
    • 函數參數個數等於運算符目數

對 輸入流>>運算符 和 輸出流<<運算符 的重載

在這裏插入圖片描述

//PhoneNumber.h
#ifndef PHONENUMBER_H
#define PHONENUMBER_H

#include<string>
#include<iostream>
using namespace std;

class PhoneNumber{
    friend ostream &operator<<(ostream &,const PhoneNumber &);
    //返回的是一個ostream類型的引用(cout的引用)
    friend istream &operator>>(istream &,PhoneNumber &);
    //返回的是一個istream類型的引用(cin的引用)
private:
    string areaCode;  //3-digit area code
    string exchange;  //3-digit exchange
    string line;      //4-digit line
};

#endif
//PhoneNumber.cpp
#include<iomanip>
#include<iostream>
#include"PhoneNumber.h"
using namespace std;

ostream &operator<<(ostream &output,const PhoneNumber &number) {
    output<<"("<<number.areaCode<<")"<<number.exchange<<"-"<<number.line;
    return output;
    //Important! Enable cout<<a<<b<<c; 
}

istream &operator>>(istream &input,PhoneNumber &number) {
    input.ignore();    //skip (
    input>>setw(3)>>number.areaCode;
    input.ignore(2);   //skip )and space
    input>>setw(3)>>number.exchange;
    input>>ignore();   //skip -
    input>>setw(4)>>number.line;
    return input;
    //Important! Enable cin>>a>>b>>c;
}
#include<iostream>
using namespace std;

int main() 
{
    PhoneNumber phone;
    cout<<"Enter phone number in the form (123) 456-7890: "<<endl;
    cin>>phone;
    cout<<"The phone number entered was: ";
    cout<<phone<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章