C語言運(yùn)算符的重載詳解
運(yùn)算符重載的規(guī)則
- 思考:用“+”、“-”能夠?qū)崿F(xiàn)復(fù)數(shù)的加減運(yùn)算嗎?
- 實(shí)現(xiàn)復(fù)數(shù)加減運(yùn)算的方法:
——重載“+”、“-”運(yùn)算符
- 運(yùn)算符重載是對(duì)已有的運(yùn)算符賦予多重含義,使同一個(gè)運(yùn)算符作用于不同類型的數(shù)據(jù)時(shí)導(dǎo)致不同的行為。
- C++ 幾乎可以重載全部的運(yùn)算符,而且只能夠重載C++中已經(jīng)有的。
不能重載的運(yùn)算符:“.”、“.*”、“::”、“?:”
- 重載之后運(yùn)算符的優(yōu)先級(jí)和結(jié)合性都不會(huì)改變。
- 運(yùn)算符重載是針對(duì)新類型數(shù)據(jù)的實(shí)際需要,對(duì)原有運(yùn)算符進(jìn)行適當(dāng)?shù)母脑?。例如?
使復(fù)數(shù)類的對(duì)象可以用“+”運(yùn)算符實(shí)現(xiàn)加法;
使時(shí)鐘類對(duì)象可以用“++”運(yùn)算符實(shí)現(xiàn)時(shí)間增加1秒。
- 重載為類的非靜態(tài)成員函數(shù);
- 重載為非成員函數(shù)。
1. 運(yùn)算符重載為成員函數(shù)
重載為類成員的運(yùn)算符函數(shù)定義形式:
函數(shù)類型 operator 運(yùn)算符(形參)
{
......
}
參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù)-1 (后置++、--除外)
雙目運(yùn)算符重載規(guī)則
- 如果要重載 B 為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 oprd1 B oprd2,其中 oprd1 為A 類對(duì)象,則 B 應(yīng)被重載為 A 類的成員函數(shù),形參類型應(yīng)該是 oprd2 所屬的類型。
- 經(jīng)重載后,表達(dá)式 oprd1 B oprd2 相當(dāng)于 oprd1.operator B(oprd2) 。
例1 復(fù)數(shù)類加減法運(yùn)算重載為成員函數(shù)
要求:將+、-運(yùn)算重載為復(fù)數(shù)類的成員函數(shù)。
規(guī)則:實(shí)部和虛部分別相加減。
操作數(shù):兩個(gè)操作數(shù)都是復(fù)數(shù)類的對(duì)象。
#include<iostream> using namespace std; //定義復(fù)數(shù)類 class Complex { public: Complex(double x=0.0, double y=0.0); //構(gòu)造函數(shù) Complex(const Complex &c); //復(fù)制構(gòu)造函數(shù) ~Complex(); //析構(gòu)函數(shù) void display() const; //復(fù)數(shù)打印函數(shù) Complex operator +(const Complex &c) const; //加法運(yùn)算符重載 Complex operator -(const Complex &c) const; //減法運(yùn)算符重載 private: double real; //實(shí)部 double imag; //虛部 }; Complex::Complex(double x, double y): real(x), imag(y){} Complex::~Complex(){} Complex::Complex(const Complex &c): real(c.real), imag(c.imag){} void Complex::display() const { cout<<"("<<real<<", "<<imag<<")"<<endl; } Complex Complex::operator +(const Complex &c) const { Complex temp; temp.real = real + c.real; temp.imag = imag + c.imag; return temp; /*或者創(chuàng)建一個(gè)臨時(shí)無名對(duì)象作為返回值*/ //return Complex(real+c.real, imag+c.imag); } Complex Complex::operator -(const Complex &c) const { Complex temp; temp.real = real - c.real; temp.imag = imag - c.imag; return temp; } int main() { Complex c1(6.7, 4.4); Complex c2(3.2, 1.7); cout<<"c1 = "; c1.display(); cout<<endl; cout<<"c2 = "; c2.display(); cout<<endl; Complex c3, c4; c3 = c1 + c2; c4 = c1 - c2; cout<<"c1 + c2 = "; c3.display(); cout<<endl; cout<<"c1 - c2 = "; c4.display(); cout<<endl; return 0; }
運(yùn)行結(jié)果:
c1 = (6.7, 4.4)
c2 = (3.2, 1.7)
c1 + c2 = (9.9, 6.1)
c1 - c2 = (3.5, 2.7)
前置單目運(yùn)算符++和--重載規(guī)則
- 如果要重載 U 為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 U oprd,其中 oprd 為A類對(duì)象,則 U 應(yīng)被重載為 A 類的成員函數(shù),無形參。
- 經(jīng)重載后,表達(dá)式 U oprd 相當(dāng)于 oprd.operator U()。
后置單目運(yùn)算符++和--重載規(guī)則
- 如果要重載 ++或--為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 oprd++ 或 oprd-- ,其中 oprd 為A類對(duì)象,則 ++或-- 應(yīng)被重載為 A 類的成員函數(shù),且具有一個(gè) int 類型形參。
- 經(jīng)重載后,表達(dá)式 oprd++ 相當(dāng)于 oprd.operator ++(0)。
例2 重載前置++和后置++為時(shí)鐘類成員函數(shù)
前置單目運(yùn)算符,重載函數(shù)沒有形參。
后置++運(yùn)算符,重載函數(shù)需要有一個(gè)int形參。
操作數(shù)是時(shí)鐘類的對(duì)象。
實(shí)現(xiàn)時(shí)間增加1秒鐘。
#include<iostream> using namespace std; class Clock { public: Clock(int hour=0, int minute=0, int second=0); ~Clock(); void showTime() const; Clock& operator ++(); //前置單目運(yùn)算符重載 Clock operator ++(int); //后置單目運(yùn)算符重載 private: int hour; int minute; int second; }; Clock::Clock(int hour, int minute, int second) { if(0<=hour && hour<24 && 0<=minute && minute<60 && 0<=second && second<60) { this->hour = hour; this->minute = minute; this->second = second; } else { cout<<"Time error!"<<endl; } } Clock::~Clock(){} void Clock::showTime() const { cout<<hour<<":"<<minute<<":"<<second<<endl; } Clock& Clock::operator ++() //函數(shù)返回值是對(duì)象的引用是為了更高效(減少臨時(shí)對(duì)象的生成) { second++; if(second >= 60) { second %= 60; minute++; if(minute >= 60) { minute %= 60; hour = (hour + 1) % 24; } } return *this; } Clock Clock::operator ++(int) //注意形參表中的整型參數(shù) { Clock old = *this; ++(*this); //調(diào)用前置“++”運(yùn)算符 /*也可以寫具體: second++; if(second >= 60) { second %= 60; minute++; if(minute >= 60) { minuet %= 60; hour = (hour + 1) % 24; } } */ return old; } int main() { Clock myClock(23, 59, 59); cout << "First time output: "; myClock.showTime(); cout << "Show myClock++: "; (myClock++).showTime(); cout << "Show ++myClock: "; (++myClock).showTime(); return 0; }
運(yùn)行結(jié)果:
First time output: 23:59:59
Show myClock++: 23:59:59
Show ++myClock: 0:0:1
2. 運(yùn)算符重載為非成員函數(shù)
有些運(yùn)算符不能重載為成員函數(shù),例如二元運(yùn)算符的左操作數(shù)不是對(duì)象,或者是不能由我們重載運(yùn)算符的對(duì)象。
運(yùn)算符重載為非成員函數(shù)的規(guī)則
- 函數(shù)的形參代表依自左至右次序排列的各操作數(shù)。
- 重載為非成員函數(shù)時(shí):
參數(shù)個(gè)數(shù)=原操作數(shù)個(gè)數(shù)(后置++、--除外)。
- 至少應(yīng)該有一個(gè)自定義類型的參數(shù)。
- 后置單目運(yùn)算符++和--的重載函數(shù),形參列表中要增加一個(gè)int,但不必寫形參名。
- 如果在運(yùn)算符的重載函數(shù)中需要操作某類對(duì)象的私有成員,可以將此函數(shù)聲明為該類的友元。
- 雙目運(yùn)算符B重載后, 表達(dá)式oprd1 B oprd2等同于operator B(oprd1,oprd2)。
- 前置單目運(yùn)算符B重載后,表達(dá)式B oprd等同于operator B(oprd)。
- 后置單目運(yùn)算符++和--重載后,表達(dá)式oprd B等同于operator B(oprd,0)。
例3 重載 Complex 的加減法和“<<”運(yùn)算符為非成員函數(shù)
- 將+、‐(雙目)重載為非成員函數(shù),并將其聲明為復(fù)數(shù)類的友元,兩個(gè)操作數(shù)都是復(fù)數(shù)類的常引用(使用常引用,既保證程序執(zhí)行的高效率,又保護(hù)數(shù)據(jù)不被隨意篡改)。
- 將<<(雙目)重載為非成員函數(shù),并將其聲明為復(fù)數(shù)類的友元,它的左操作數(shù)是std::ostream引用,右操作數(shù)為復(fù)數(shù)類的常引用,返回std::ostream引用,用以支持下面形式的輸出:
cout << a << b;
該輸出調(diào)用的是:
operator << (operator << (cout, a), b);
#include<iostream> using namespace std; class Complex { public: Complex(double x=0.0, double y=0.0); ~Complex(); friend Complex operator +(const Complex &c1, const Complex &c2); //聲明為類的友元 friend Complex operator -(const Complex &c1, const Complex &c2); friend ostream& operator <<(ostream &out, const Complex &c); private: double real; double imag; }; Complex::Complex(double x, double y): real(x), imag(y){} Complex::~Complex(){} Complex operator +(const Complex &c1, const Complex &c2) { Complex temp; temp.real = c1.real + c2.real; temp.imag = c1.imag + c2.imag; return temp; /*或者創(chuàng)建一個(gè)臨時(shí)無名對(duì)象作為返回值*/ //return Complex(c1.real+c2.real, c1.imag+c2.imag); } Complex operator -(const Complex &c1, const Complex &c2) { return Complex(c1.real-c2.real, c1.imag-c2.imag); } ostream& operator <<(ostream& out, const Complex &c) { out<<"("<<c.real<<", "<<c.imag<<")"; return out; } /*若輸出為復(fù)數(shù)的標(biāo)準(zhǔn)形式: 在復(fù)數(shù)兩端加上括號(hào),實(shí)部和虛部均保留兩位小數(shù), 如(8.23+2.00i)、(7.45-3.40i)*/ /* ostream& operator <<(ostream& out, const Complex &c) { if(c.imag>0) out<<setiosflags(ios::fixed)<<setprecision(2)<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl; else out<<setiosflags(ios::fixed)<<setprecision(2)<<"("<<c.real<<c.imag<<"i)"<<endl; return out; } */ int main() { Complex c1(5, 4), c2(2, 10), c3; cout << "c1 = " << c1 << endl; cout << "c2 = " << c2 << endl; c3 = c1 - c2; //使用重載運(yùn)算符完成復(fù)數(shù)減法 cout << "c3 = c1 - c2 = " << c3 << endl; c3 = c1 + c2; //使用重載運(yùn)算符完成復(fù)數(shù)加法 cout << "c3 = c1 + c2 = " << c3 << endl; return 0; }
運(yùn)行結(jié)果:
c1 = (5, 4)
c2 = (2, 10)
c3 = c1 - c2 = (3, -6)
c3 = c1 + c2 = (7, 14)
類的友元函數(shù)重載插入運(yùn)算符和重載提取運(yùn)算符在調(diào)用時(shí)只需像平常cin >> xxx 或 cout << xxx即可,而類的成員函數(shù)重載插入運(yùn)算符和重載提取運(yùn)算符在調(diào)用時(shí)是要xxx >> cin 或 xxx << cout,剛好和平常的用法是相反的。而xxx >> cin相當(dāng)于xxx.operator>>(cin);xxx << cout相當(dāng)于xxx.operator<<(cout)。
用引用&,減少對(duì)象拷貝,增加速度和效率。插入和提取運(yùn)算符,操作的對(duì)象是ostream和istream。如果不加&的話,程序也是沒問題的,可以運(yùn)行。但是在每次調(diào)用<<操作的時(shí)候,都會(huì)產(chǎn)生一個(gè)新的臨時(shí)的ostream對(duì)象。包括對(duì)“=”運(yùn)算符的重載也是一樣。“=”更能說明這個(gè)問題。一般來說是 xxx & opreator = (xxx a);就是因?yàn)槲覀兿M麑?duì)于a=b; 把b的值直接賦值給a就好了,用xxx &做返回類型,返回的是a的別名/引用,不會(huì)創(chuàng)建新的臨時(shí)對(duì)象。如果沒有&,那么會(huì)創(chuàng)建新的臨時(shí)值返回,低效。重點(diǎn)就是對(duì)引用&的使用的理解。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
深入理解C++的動(dòng)態(tài)綁定與靜態(tài)綁定的應(yīng)用詳解
本篇文章是對(duì)C++中的動(dòng)態(tài)綁定與靜態(tài)綁定進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05探討:將兩個(gè)鏈表非降序合并為一個(gè)鏈表并依然有序的實(shí)現(xiàn)方法
本篇文章是對(duì)將兩個(gè)鏈表非降序合并為一個(gè)鏈表并依然有序的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C語言如何利用輾轉(zhuǎn)相除法求最大公約數(shù)
這篇文章主要介紹了C語言如何利用輾轉(zhuǎn)相除法求最大公約數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08C++使用宏實(shí)現(xiàn)動(dòng)態(tài)庫(kù)加載
開發(fā)的時(shí)候,有些項(xiàng)目不能靜態(tài)鏈接動(dòng)態(tài)庫(kù),需要程序運(yùn)行時(shí)加載動(dòng)態(tài)庫(kù)。本文將使用宏來實(shí)現(xiàn)動(dòng)態(tài)庫(kù)的加載,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12