C++11運(yùn)算符重載和向量類(lèi)重載實(shí)例詳解(<<,>>,+,-,*等)
1. C++運(yùn)算符重載介紹
C ++ 中預(yù)定義的運(yùn)算符的操作對(duì)象只能是基本數(shù)據(jù)類(lèi)型。但實(shí)際上,對(duì)于許多用戶(hù)自定義類(lèi)型(例如類(lèi)),也需要類(lèi)似的運(yùn)算操作。這時(shí)就必須在C ++ 中重新定義這些運(yùn)算符,賦予已有運(yùn)算符新的功能,使它能夠用于特定類(lèi)型執(zhí)行特定的操作。運(yùn)算符重載的實(shí)質(zhì)是函數(shù)重載,它提供了C ++ 的可擴(kuò)展性,也是C ++ 最吸引人的特性之一。
運(yùn)算符重載時(shí)要遵循以下規(guī)則:
( 1 ) 除了類(lèi)屬關(guān)系運(yùn)算符 " . " 、成員指針運(yùn)算符 " .* " 、作用域運(yùn)算符 " :: " 、sizeof運(yùn)算符和三目運(yùn)算符 " ?: " 以外,C ++ 中的所有運(yùn)算符都可以重載。
( 2 ) 重載運(yùn)算符限制在C ++ 語(yǔ)言中已有的運(yùn)算符范圍內(nèi)的允許重載的運(yùn)算符之中,不能創(chuàng)建新的運(yùn)算符。
( 3 ) 運(yùn)算符重載實(shí)質(zhì)上是函數(shù)重載,因此編譯程序?qū)\(yùn)算符重載的選擇,遵循函數(shù)重載的選擇原則。
( 4 ) 重載之后的運(yùn)算符不能改變運(yùn)算符的優(yōu)先級(jí)和結(jié)合性,也不能改變運(yùn)算符操作數(shù)的個(gè)數(shù)及語(yǔ)法結(jié)構(gòu)。
( 5 ) 運(yùn)算符重載不能改變?cè)撨\(yùn)算符用于內(nèi)部類(lèi)型對(duì)象的含義。它只能和用戶(hù)自定義類(lèi)型的對(duì)象一起使用,或者用于用戶(hù)自定義類(lèi)型的對(duì)象和內(nèi)部類(lèi)型的對(duì)象混合使用時(shí)。
( 6 ) 運(yùn)算符重載是針對(duì)新類(lèi)型數(shù)據(jù)的實(shí)際需要對(duì)原有運(yùn)算符進(jìn)行的適當(dāng)?shù)母脑?,重載的功能應(yīng)當(dāng)與原有功能相類(lèi)似,避免沒(méi)有目的地使用重載運(yùn)算符。
1.1 單目運(yùn)算符與雙目運(yùn)算符
( 1 ) 雙目運(yùn)算符重載為類(lèi)的成員函數(shù)時(shí),函數(shù)只顯式說(shuō)明一個(gè)參數(shù),該形參是運(yùn)算符的右操作數(shù)。
比如說(shuō)你重載+號(hào),如果寫(xiě)在類(lèi)外面,那么是需要兩個(gè)參數(shù)的,而寫(xiě)在類(lèi)里面,只能寫(xiě)一個(gè)參數(shù),因?yàn)楫?dāng)這個(gè)函數(shù)被調(diào)用的時(shí)候,會(huì)自動(dòng)的傳一個(gè)this指針進(jìn)去,就是對(duì)象本身,所以只需要一個(gè)參數(shù)
( 2 ) 前置單目運(yùn)算符重載為類(lèi)的成員函數(shù)時(shí),不需要顯式說(shuō)明參數(shù),即函數(shù)沒(méi)有形參。
( 3 ) 后置單目運(yùn)算符重載為類(lèi)的成員函數(shù)時(shí),函數(shù)要帶有一個(gè)整型形參。
比如前置++,和后置++,帶一個(gè)整形形參只是為了區(qū)分
1.2 友元運(yùn)算符
有些運(yùn)算符是一定得聲明為友元的,比如<<,>>運(yùn)算符
因?yàn)?,+這些運(yùn)算符,是c++最基本的運(yùn)算符,而>>,<<運(yùn)算符是標(biāo)準(zhǔn)頭文件里面的一個(gè)類(lèi)里面寫(xiě)的,你不能把這個(gè)函數(shù)聲明為你這個(gè)自定義類(lèi)的函數(shù),因?yàn)檫@是別人類(lèi)里面的函數(shù),因此你只能把它聲明為友元函數(shù),聲明為友元函數(shù)之后,那么這個(gè)函數(shù)它就可以訪(fǎng)問(wèn)你這個(gè)自定義類(lèi)里面的私有成員變量
2. 實(shí)例講解
光看這些概念,想必沒(méi)有接觸過(guò)的同學(xué)頭都大了,接下來(lái)我通過(guò)一個(gè)向量類(lèi)的例子,來(lái)講解一下各個(gè)運(yùn)算符重載怎么用
2.1 頭文件定義
這次我們來(lái)實(shí)例一個(gè)向量類(lèi),什么是向量類(lèi)呢,就是數(shù)學(xué)里面的向量,一個(gè)括號(hào),里面兩個(gè)數(shù)字,看一下頭文件你就明白啦
class Vec2D { private: double x_; double y_; public: static string AuthorBlog = "https://www.cnblogs.com/wanghongyang"; Vec2D(double x, double y) :x_(x), y_(y) {} Vec2D() { x_ = 0.0; y_ = 0.0; } std::string toString(); friend Vec2D operator+(const Vec2D& v1, const Vec2D& v2); friend Vec2D operator-(const Vec2D& v1, const Vec2D& v2); friend double operator*(const Vec2D& v1, const Vec2D& v2); friend Vec2D operator+(const Vec2D& v1, double num); friend Vec2D operator*(const double num, const Vec2D& v2); friend Vec2D operator*(const Vec2D& v2, const double num); friend istream& operator>>(istream& stream, Vec2D& v1); friend std::ostream& operator<<(std::ostream& stream, const Vec2D& v1); Vec2D negative(); Vec2D operator-(); Vec2D operator++(); Vec2D operator++(int dummy); Vec2D operator--(); Vec2D operator+=(const Vec2D& v); Vec2D operator-=(const Vec2D& v); double& operator[](const int& index); double magnitude(); double direction(); int compareTo(Vec2D& v2); operator double(); double getX()const { return x_; } double getY() const { return y_; } void setX(double x) { x_ = x; } void setY(double y) { y_ = y; } };
可以看到,其實(shí)私有成員就是 x_和y_,然后我重載了非常多的函數(shù),下面我們來(lái)看一下具體的實(shí)現(xiàn)
2.2 實(shí)現(xiàn)運(yùn)算符重載
toString函數(shù)
這個(gè)函數(shù)我就不多說(shuō)啦,比較簡(jiǎn)單
std::string Vec2D::toString() { std::string res = "(" + std::to_string(getX()) + ", " + std::to_string(getY()) + ")"; return res; }
negative函數(shù)
這個(gè)函數(shù)是用來(lái)將向量變成負(fù)方向
Vec2D Vec2D::negative() { return Vec2D(-1 * x_, -1 * y_); }
operator-函數(shù)
第一個(gè)重載函數(shù)出現(xiàn)了,是重載的符號(hào),更加方便的實(shí)現(xiàn)了改變向量為負(fù)方向的操作
這樣我們可以通過(guò) -a,-b的形式來(lái)調(diào)用
Vec2D Vec2D::operator-() { return Vec2D(-1 * x_, -1 * y_); }
operator++函數(shù)
這個(gè)函數(shù)是前置++運(yùn)算符,返回*this就是返回當(dāng)前對(duì)象
Vec2D Vec2D::operator++() { x_++; y_++; return *this; }
operator++函數(shù)
這個(gè)函數(shù)是后置++運(yùn)算符,所以后面加了一個(gè)類(lèi)型的參數(shù),這個(gè)參數(shù)唯一的意思是與前置++作區(qū)分
我們首先創(chuàng)建了一個(gè)臨時(shí)變量,然后將本身的x,y加1,返回的卻是臨時(shí)變量,這樣就實(shí)現(xiàn)了后置++的操作
static string AuthorBlog = "https://www.cnblogs.com/wanghongyang"; Vec2D Vec2D::operator++(int dummy) { Vec2D ret(x_, y_); x_++; y_++; return ret; }
operator--函數(shù)
減減同理,就是將x,y都減1
static string AuthorBlog = "https://www.cnblogs.com/wanghongyang"; Vec2D Vec2D::operator--() { x_ -= 1; y_ -= 1; return *this; }
operator+= ,-=函數(shù)
這兩個(gè)函數(shù)比較相似,我就放到一起講啦,這里是將調(diào)用這個(gè)函數(shù)本身的對(duì)象,與參數(shù)里面的v相加或者相減
static string AuthorBlog = "https://www.cnblogs.com/wanghongyang"; Vec2D Vec2D::operator+=(const Vec2D& v) { x_ += v.x_; y_ += v.y_; return *this; } Vec2D Vec2D::operator-=(const Vec2D& v) { x_ -= v.x_; y_ -= v.y_; return *this; }
operator[ ]函數(shù)
這里重載了[ ],有一個(gè)參數(shù),index,用來(lái)選擇到底是返回x還是y
static string AuthorBlog = "https://www.cnblogs.com/wanghongyang"; double& Vec2D::operator[](const int& index) { if (index == 0) { return x_; } else if (index == 1) { return y_; } else { printf("subscript error\n"); exit(0); } }
operator+(類(lèi)外)函數(shù)
因?yàn)槭窃陬?lèi)外重載,所以有兩個(gè)參數(shù),同時(shí)要注意將這個(gè)函數(shù)聲明為友元函數(shù),因?yàn)檫@樣才可以訪(fǎng)問(wèn)私有成員變量
static string AuthorBlog = "https://www.cnblogs.com/wanghongyang"; //類(lèi)外重載,運(yùn)算符重載函數(shù)作為類(lèi)的友元函數(shù) Vec2D operator+(const Vec2D& v1, const Vec2D& v2) { Vec2D ret; ret.setX(v1.getX() + v2.getX()); ret.setY(v1.getY() + v2.getY()); return ret; } Vec2D operator+(const Vec2D& v1, double num) { Vec2D ret; ret.setX(v1.getX() + num); ret.setY(v1.getY() + num); return ret; }
operator*函數(shù)
這里重載了*,用來(lái)實(shí)現(xiàn)向量之間的相乘
static string AuthorBlog = "https://www.cnblogs.com/wanghongyang"; Vec2D operator*(const double num, const Vec2D& v2) { Vec2D ret; ret.setX(num * v2.getX()); ret.setY(num * v2.getY()); return ret; }
重載>> <<
這里給大家避個(gè)坑,一定要引入iostream頭文件,而不是用using
這兩個(gè)函數(shù)就是用來(lái)實(shí)現(xiàn)cout和cin
可以看到,實(shí)現(xiàn)cin 是通過(guò) istream對(duì)象來(lái)實(shí)現(xiàn)的
實(shí)現(xiàn)cout 是通過(guò)ostream來(lái)實(shí)現(xiàn)的
記得在最后返回istream或者ostream對(duì)象
istream& operator>>(istream& stream, Vec2D& v1) { double x, y; stream >> x >> y; v1.setX(x); v1.setY(y); // 也可以直接 // stream >> x_ >> y_; return stream; } ostream& operator<<(ostream& stream, const Vec2D& v1) { std::string res = "(" + std::to_string(v1.getX()) + ", " + std::to_string(v1.getY()) + ")"; stream << res; return stream; }
總結(jié)
到此這篇關(guān)于C++11運(yùn)算符重載和向量類(lèi)重載的文章就介紹到這了,更多相關(guān)C++11運(yùn)算符重載向量類(lèi)重載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用代碼驗(yàn)證linux子進(jìn)程與父進(jìn)程的關(guān)系
Linux下父進(jìn)程可以使用fork 函數(shù)創(chuàng)建子進(jìn)程,但是當(dāng)父進(jìn)程先退出后,子進(jìn)程會(huì)不會(huì)也退出呢?通過(guò)下面這個(gè)小實(shí)驗(yàn),我們能夠很好的看出來(lái)2014-02-02C語(yǔ)言實(shí)現(xiàn)循環(huán)單鏈表的示例代碼
這篇文章主要給大家詳細(xì)介紹了C語(yǔ)言如何實(shí)現(xiàn)循環(huán)單鏈表,文章通過(guò)代碼示例講解的非常詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的小伙伴跟著小編一起來(lái)看看吧2023-08-08C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單彈跳球游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單彈跳球游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03C++11如何實(shí)現(xiàn)無(wú)鎖隊(duì)列
這篇文章主要介紹了C++11如何實(shí)現(xiàn)無(wú)鎖隊(duì)列,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08