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