日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++从0到1的入门级教学(十二)——运算符重载

發(fā)布時(shí)間:2023/12/9 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++从0到1的入门级教学(十二)——运算符重载 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 12 運(yùn)算符重載
    • 12.1 加法運(yùn)算符重載
    • 12.2 左移運(yùn)算符重載
      • 12.2.1 演示與說明
      • 12.2.2 常見的友元使用:重載>>運(yùn)算符
    • 12.3 遞增運(yùn)算符重載
    • 12.4 賦值運(yùn)算符重載
    • 12.5 關(guān)系運(yùn)算符重載
    • 12.6 函數(shù)調(diào)用運(yùn)算符重載

12 運(yùn)算符重載

在本講中,我們會(huì)設(shè)計(jì)到一些使得對象操作更美觀的技術(shù)——運(yùn)算符重載。運(yùn)算符重載是一種C++多態(tài)的形式。

運(yùn)算符通過重載,可以實(shí)現(xiàn)其原本沒有的含義。C++允許運(yùn)算符重載擴(kuò)展到用戶定義的類型,如將兩個(gè)對象相加。

我們前面實(shí)際上學(xué)過數(shù)組,如果要將兩個(gè)數(shù)組的對應(yīng)元素相加,我們需要寫一個(gè)for循環(huán)來遍歷數(shù)組中的元素,并且分別進(jìn)行相加。實(shí)際上,這就是一種簡單的重載,我們口頭上所說的arr1+arr2,實(shí)際上賦予了——加是對應(yīng)元素相加的這層含義。

所以,為了簡化它的意思,我們可以將對應(yīng)元素相加后的新數(shù)組寫為以下的形式:

arr3 = arr1+arr2

總結(jié)上述所講:運(yùn)算符重載的含義是:對已有的運(yùn)算符重新進(jìn)行定義,賦予其另一種功能,以適應(yīng)不同的數(shù)據(jù)類型。

重載的通用格式如下所示:

operator op(argument - list)

op指的是C++現(xiàn)有的運(yùn)算符;例如加法運(yùn)算符重載為operator +()。當(dāng)然C++以外的、虛構(gòu)的運(yùn)算符不可重載,這是需要注意的。

12.1 加法運(yùn)算符重載

對于內(nèi)置數(shù)據(jù)類型,編譯器知道如何進(jìn)行運(yùn)算:

  • int a = 10;
  • int b = 10;
  • int c = a+b

但是我們假如是下面這種情況呢?

class Person { public:int m_A;int m_B;}Person p1; p1 m_A = 10; p1 m_B = 10;Person p2; Person p1; p2 m_A = 10; p2 m_B = 10;Person p3 = p1+p2;

在這種情況下,C++編譯器就會(huì)蒙了,Person是啥類型,怎么還能相加?

我們實(shí)際上可以編寫一個(gè)成員函數(shù)來實(shí)現(xiàn)此功能,實(shí)現(xiàn)兩個(gè)對象相加屬性后返回新的對象。而對于C++來說,為了指明是加法運(yùn)算符的作用發(fā)生了變化,故該函數(shù)統(tǒng)一命名為operatao +。

如果你按照它的命名規(guī)則來了,那么在調(diào)用函數(shù)時(shí),你就可以使用p3 = p1+p2的格式去調(diào)用這個(gè)函數(shù)。

以上的方式我們叫做通過成員函數(shù)來重載+號(hào)運(yùn)算符,除此之外,我們還可以通過全局函數(shù)來重載+號(hào)運(yùn)算符。

讓我們看看下面的例子來理解我上述的話。

#include <iostream> using namespace std;//加號(hào)運(yùn)算符重載 class Person { public://成員函數(shù)重載+號(hào)/*Person operator+(Person p) {Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}*/int m_A;int m_B;private:};//全局函數(shù)重載+號(hào) Person operator+(Person& p1,Person& p2) {Person temp;temp.m_A = p1.m_A + p2.m_A;temp.m_B = p1.m_B + p2.m_B;return temp; }void test01() {Person p1;p1.m_A = 10;p1.m_B = 10;Person p2;p2.m_A = 10;p2.m_B = 10;Person p3 = p1 + p2;cout << "p3.m_A:" << p3.m_A << endl;cout << "p3.m_B:" << p3.m_B << endl; }int main() {test01(); }

out:

運(yùn)算符重載也可以發(fā)生函數(shù)重載。這樣的原因是可以應(yīng)對多種情況。如p3 = p2+10,對于10,我們并沒有寫出對應(yīng)解決的方案函數(shù),所以如果運(yùn)算符重載不能發(fā)送函數(shù)重載,那么就對運(yùn)算符不太友好了。

總的來說,加法運(yùn)算符就是使得自定義的數(shù)據(jù)類型能夠按照自己想要的方式相加。需要注意的是,對于內(nèi)置的數(shù)據(jù)類型的操作運(yùn)算符是不可改變的;并且,對于運(yùn)算符的重載不要濫用。

12.2 左移運(yùn)算符重載

12.2.1 演示與說明

左移運(yùn)算符指的是我們在輸出的時(shí)候使用的那個(gè)運(yùn)算符。

cout<<a<<endl;

如果是對于內(nèi)置的基本數(shù)據(jù)類型,那肯定是可以利用左移運(yùn)算符來進(jìn)行輸出的。但是如果是對象呢?

Person p; cout<<p<<endl;

這樣的對象輸出的結(jié)果肯定是不被允許的,如下所示。

對此,我們可以通過重載左移運(yùn)算符來獲得我們想要的效果。

我們前面說過可以通過成員函數(shù)和全局函數(shù)來重載,但是對于左移運(yùn)算符,其并不能在成員函數(shù)中被重載,因?yàn)檫壿嫴粚ΑK?#xff0c;對于通常的左移運(yùn)算符重載,我們都是在全局函數(shù)中去實(shí)現(xiàn)它。

試著敲一下下面的代碼你就能理會(huì)其中的思想了。

#include <iostream> using namespace std;class Person { public:int m_A;int m_B; };//只能利用全局函數(shù)重載左移運(yùn)算符 void operator<<(ostream& cout, Person& p) {cout << "m_A = " << p.m_A << "m_B = " << p.m_B ; }void test01() {Person p1;p1.m_A = 10;p1.m_B = 20;cout << p1 ; }int main() {test01();system("pause"); }

out:

我們實(shí)際上可以嘗試在重載過后的<<寫上這樣的代碼:

cout<<p1<<endl;

很快地,你會(huì)發(fā)現(xiàn)報(bào)錯(cuò)了。報(bào)錯(cuò)的原因是因?yàn)?#xff0c;你的重載函數(shù)并沒有返回值,而對于cout之所以可以使用兩個(gè)左移運(yùn)算符,是因?yàn)槠鋬?nèi)含有鏈?zhǔn)骄幊痰乃枷搿9?#xff0c;如果想要使得可以連續(xù)使用<<,我們必須將函數(shù)的返回值改為cout即可。

順便提一句,cout是ostream實(shí)例化的結(jié)果,即輸出對象。

ostream對象?

ostream對象是指輸出流對象,通常來說,cout輸出的對象是指顯示器,當(dāng)然,還有輸入流對象ofstream,這些我們到后面再去提及。

我們將以上的代碼改寫為如下即可實(shí)現(xiàn)多次使用<<:

#include <iostream> using namespace std;class Person { public:int m_A;int m_B; };//只能利用全局函數(shù)重載左移運(yùn)算符 ostream& operator<<(ostream& cout, Person& p) {cout << "m_A = " << p.m_A << "m_B = " << p.m_B ;return cout; }void test01() {Person p1;p1.m_A = 10;p1.m_B = 20;cout << p1 << endl; }int main() {test01();system("pause"); }

out:

為什么使用引用?

在上述的代碼中實(shí)際上兩個(gè)位置使用到了引用。返回值和參數(shù)是引用的原因是:我們自始至終都想這對cout這個(gè)對象做功能上的修改,而不是從ostream再創(chuàng)建一個(gè)cout對象,然后賦予它新功能。故,我們要加上引用。

12.2.2 常見的友元使用:重載>>運(yùn)算符

在實(shí)際開發(fā)中,我們實(shí)際上會(huì)把成員屬性寫入私有,這樣的話,對于重載函數(shù)無法訪問,我們只需要利用友元即可解決這個(gè)問題。

#include <iostream> using namespace std;class Person {friend ostream& operator<<(ostream& cout, Person& p); private:int m_A =10;int m_B = 20; };//重載左移運(yùn)算符 ostream& operator<<(ostream& cout, Person& p) {cout << "m_A = " << p.m_A << "m_B = " << p.m_B;return cout; }void test01() {Person p1;cout << p1 << endl; }int main() {test01(); }

out:

12.3 遞增運(yùn)算符重載

我們來看看遞增運(yùn)算符的原理。

int a = 10;cout<< ++a <<endl;//11 cout << a <<endl; //結(jié)果為11cout <<b++<<endl;//10 cout << b <<endl;//11

對于++a,其原理為先做++操作再輸出,而對于b++,其原理為先輸出再++。

同樣地,我們對對象做自增操作,其原理如下:

class MyInteger { public:MyInteger(){m_Num = 0;}private:int m_Num; }MyInteger myint; cout <<myint<<endl; //0 cout << ++myint <<endl; //1 cout << myint++ <<endl; //1 cout << myint <<endl; //2

我們來試著實(shí)現(xiàn)上述的原理:

#include <iostream> using namespace std;class MyInteger {friend ostream& operator<<(ostream& cout, MyInteger myint); public:MyInteger() {m_Num = 0;}//局部函數(shù)重載++運(yùn)算符(前置++)MyInteger& operator++() //返回一個(gè)引用是為了一直對一個(gè)數(shù)據(jù)進(jìn)行操作{m_Num++;return *this;}//局部函數(shù)重載++運(yùn)算符(后置++)MyInteger operator++(int) //不能返回引用,因?yàn)榇藭r(shí)返回值是局部變量{//1 記錄當(dāng)前結(jié)果MyInteger temp = *this;//2 遞增m_Num++;//3 將記錄結(jié)果返回return temp;}private:int m_Num; };ostream& operator<<(ostream& cout, MyInteger myint) {cout << myint.m_Num;return cout; }void test01() {MyInteger myint;cout << ++myint << endl; }void test02() {MyInteger mying;cout << mying++ << endl;cout << mying << endl; }int main() {test01();test02();system("pause"); }

12.4 賦值運(yùn)算符重載

賦值運(yùn)算符的重載原理涉及到深淺拷貝,我們從代碼中理解比較好。

#include <iostream> using namespace std;//賦值運(yùn)算符重載 class Person { public:Person(int age) {m_Age = new int(age);}~Person() {if (m_Age != NULL) {delete(m_Age);m_Age = NULL;}}int* m_Age; };void test01() {Person p1(18);Person p2(20);p2 = p1;//賦值操作cout << "p1的年齡為:" << *p1.m_Age << endl;cout << "p2的年齡為:" << *p2.m_Age << endl;}int main() {test01();system("pause");return 0; }

從以上的代碼中,我們會(huì)發(fā)現(xiàn)無法運(yùn)行,根本原因是因?yàn)?#xff1a;

也就是說,根本原因是因?yàn)樵瓉淼馁x值運(yùn)算符提供的是一個(gè)淺拷貝的過程,但是我們想要的是一個(gè)深拷貝的效果,故,我們需要重載賦值運(yùn)算符。如下所示:

#include <iostream> using namespace std;//賦值運(yùn)算符重載 class Person { public:Person(int age) {m_Age = new int(age);}~Person() {if (m_Age != NULL) {delete(m_Age);m_Age = NULL;}}//重載賦值運(yùn)算符Person& operator=(Person &p) {//對于編譯器來說,其提供的是淺拷貝//我們應(yīng)該需要用深拷貝//應(yīng)該先判斷是否有屬性在堆區(qū),如果有先釋放干凈,然后再深拷貝if (m_Age != NULL) {delete m_Age;m_Age = NULL;}//深拷貝m_Age = new int(*p.m_Age);//記住,要返回指針,才能實(shí)現(xiàn)鏈?zhǔn)骄幊蘲eturn *this;}int* m_Age; };void test01() {Person p1(18);Person p2(20);Person p3(30);p3 = p2 = p1;//賦值操作cout << "p1的年齡為:" << *p1.m_Age << endl;cout << "p2的年齡為:" << *p2.m_Age << endl;cout << "p3的年齡為:" << *p3.m_Age << endl; }int main() {test01();system("pause");return 0; }

out:

12.5 關(guān)系運(yùn)算符重載

對于自定義的數(shù)據(jù)類型,C++是無法提供對比方式的,如>、<、=等。為此,我們需要重載關(guān)系運(yùn)算符。

讓我們用以下的代碼來解決這個(gè)問題:

#include <iostream> using namespace std;//重載關(guān)系運(yùn)算符 class Person { public:Person(string name, int age) {m_Name = name;m_Age = age;};//重載 == 號(hào)bool operator==(Person& p) {if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {return true;}return false;}string m_Name;int m_Age;private:};void test01() {Person p1("Tom", 18);Person p2("jarry", 19);//Person p2("Tom", 18);if (p1 == p2) {cout << "相同" << endl;}else{cout << "不相同" << endl;} }int main() {test01(); }

12.6 函數(shù)調(diào)用運(yùn)算符重載

函數(shù)調(diào)用運(yùn)算符()也可以重載,需要注意的是,由于重載后使用的方式非常像函數(shù)的調(diào)用,因此稱為仿函數(shù)。仿函數(shù)沒有固定的寫法,其風(fēng)格多變。

讓我們試著敲一下下面的代碼:

#include <iostream> using namespace std; #include <string>//函數(shù)調(diào)用運(yùn)算符重載 //打印輸出類 class MyPrint { public://重載函數(shù)調(diào)用運(yùn)算符void operator()(string test) {cout << test << endl;} };class MyAdd { public://重載例子2int operator()(int num1, int num2){return num1 + num2;} };void test01() {MyPrint myPrint;myPrint("hello world"); }void test02() {MyAdd myadd;cout << "ret = " << myadd(100, 200) << endl; }int main() {test01();test02(); }

C++和Java一樣,也是創(chuàng)建一個(gè)匿名對象,匿名對象使用后當(dāng)場銷毀。如在上例中我想創(chuàng)建一個(gè)匿名對象,只需:

MyAdd()(100,100)

總結(jié)

以上是生活随笔為你收集整理的C++从0到1的入门级教学(十二)——运算符重载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。