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;
}