| 導購 | 订阅 | 在线投稿
分享
 
 
 

C++運算符重載函數基礎及其值返回狀態

來源:互聯網網民  2008-06-01 01:11:37  評論

運算符重載是C++的重要組成部分,它可以讓程序更加的簡單易懂,簡單的運算符使用可以使複雜函數的理解更直觀。

對于普通對象來說我們很自然的會頻繁使用算數運算符讓他們參與計算,但是對于自定義類的對象來說,我們是無論如何也不能阻止寫出像下面的代碼一樣的程序來的。

例子如下:

class Test

{

//過程省略

}

int main()

{

Test a,c;

c=a+a;

}

當然這樣的代碼是不能夠通過編譯的,c++對自定類的算術運算部分保留給了程序員,這也是符合c++靈活特性的。

在c++中要想實現這樣的運算就必須自定義運算符重載函數,讓它來完整具體工作。

在這裏要提醒讀者的是,自定義類的運算符重載函數也是函數,你重載的一切運算符不會因爲是你自己定義的就改變其運算的優先級,自定義運算符的運算優先級同樣遵循與內部運算符一樣的順序。

C++運算符重載函數基礎及其值返回狀態

除此之外,c++也規定了一些運算符不能夠自定義重載,例如.、::、.*、.->、?:。

下面我們來學習如何重載運算符,運算符重載函數的形式是:

返回類型 Operator 運算符符號 (參數說明)

{

//函數體的內部實現

}

運算符重載函數的使用主要分爲兩種形式,一種是作爲類的友元函數進行使用,另一種則是作爲類的成員函數進行使用。

下面我們先看一下作爲類的友元函數使用的例子:

//程序作者:管甯

//站點:www.cndev-lab.com

//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>

using namespace std;

class Test

{

public:

Test(int a = 0)

{

Test::a = a;

}

friend Test operator +(Test&,Test&);

friend Test& operator ++(Test&);

public:

int a;

};

Test operator +(Test& temp1,Test& temp2)//+運算符重載函數

{

//cout<<temp1.a<<"|"<<temp2.a<<endl;//在這裏可以觀察傳遞過來的引用對象的成員分量

Test result(temp1.a+temp2.a);

return result;

}

Test& operator ++(Test& temp)//++運算符重載函數

{

temp.a++;

return temp;

}

int main()

{

Test a(100);

Test c=a+a;

cout<<c.a<<endl;

c++;

cout<<c.a<<endl;

system("pause");

}

在例子中,我們對于自定義類Test來說,重載了加運算符與自動遞增運算符,重載的運算符完成了同類型對象的加運算和遞增運算過程

重載運算符函數返回類型和形式參數也是根據需要量進行調整的,下面我們來看一下修改後的加運算符重載函數。

代碼如下:

//程序作者:管甯

//站點:www.cndev-lab.com

//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>

using namespace std;

class Test

{

public:

Test(int a = 0)

{

Test::a = a;

}

friend Test operator +(Test&,const int&);

public:

int a;

};

Test operator +(Test& temp1,const int& temp2)//+運算符重載函數

{

Test result(temp1.a * temp2);

return result;

}

int main()

{

Test a(100);

Test c = a + 10;

cout<<c.a<<endl;

system("pause");

}

上面修改後的例子中,我們讓重載後的加運算符做的事情,事實上並不是同類型對象的加運算,而是自定義類對象與內置int常量對象的乘法運算。

值得注重的是,對于運算符重載來說,我們並不一定要用它一定要做同類型對象的加法或者是其它運算,運算符重載函數本身就是函數,那麽在函數體內部我們是可以做任何事情的,但是從不違反常規思維的角度來說,我們沒有必要讓重載加運算的函數來做與其重載的符號意義上完全不相符的工作,所以在使用重載運算符脫離原意之前,必須保證有足夠的理由。

下面我們討論一下作爲類成員函數的運算符重載函數的使用,及其函數的值返回與引用返回的差別。

下面我們先看實例,而後逐步分析。

代碼如下(重要部分做了具體的注解):

//程序作者:管甯

//站點:www.cndev-lab.com

//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>

using namespace std;

class Test

{

public:

Test(int a = 0)

{

Test::a = a;

}

Test(Test &temp)

//運算符重載函數爲值返回的時候會産生臨時變量,臨時變量與局部變量result的複制會調用拷貝構造函數,臨時變量的生命周期是在拷貝構造函數運行完成後才結束,但假如運算符重載函數返回的是引用,那麽不會産生臨時變量,而局部變量result的生命周期在運算符重載函數退出後立即消失,它的生命周期要比臨時變量短,所以當外部對象獲取返回值的內存地址所存儲的值的時候,獲得是一個已經失去效果的內存地址中的值,在這裏的值返回與引用返回的對比,證實了臨時變量的生命周期比局部變量的生命周期稍長。

{

cout<<"載入拷貝構造函數"<<"|"<<temp.a<<endl;//注重這裏,假如修改運算符重載函數爲返回引用,這裏就會出現異常,temp.a將獲得一個隨機值。

Test::a = temp.a;

}

~Test()//在mian()內析構的過程是result局部變量産生的

{

cout<<"載入析構函數!"<<endl;

cin.get();

}

Test operator +(Test& temp2)//+運算符重載函數

{

//cout<<this->a<<endl;

Test result(this->a+temp2.a);

return result;

}

Test& operator ++()//++運算符重載函數

//遞增運算符是單目運算符,使用返回引用的運算符重載函數道理就在于它需要改變自身。

//在前面我們學習引用的單元中我們知道,返回引用的函數是可以作爲左值參與運算的,這一點也符合單目運算符的特點。

//假如把該函數改成返回值,而不是返回引用的話就破壞了單目預算改變自身的特點,程序中的++(++c)運算結束後輸出c.a,會發現對象c只做了一次遞增運算,原因在于,當函數是值返回狀態的時候括號內的++c返回的不是c本身而是臨時變量,用臨時變量參與括號外的++運算,當然c的值也就只改變了一次。

{

this->a++;

return *this;

}

public:

int a;

};

int main()

{

Test a(100);

Test c=a+a;

cout<<c.a<<endl;

c++;

cout<<c.a<<endl;

++c;

cout<<c.a<<endl;

++(++c);

cout<<c.a<<endl;

system("pause");

}=版權所有 軟件 下載 學院 版權所有=

上例中運算符重載函數以類的成員函數方式出現,細心的讀者會發現加運算和遞增運算重載函數少了一個參數,這是爲什麽呢?

因爲當運算符重載函數以類成員函數身份出現的時候,C++會隱藏第一個參數,轉而取代的是一個this指針

接下來我們具體分析一下運算符重載函數的值返回與引用返回的差別。

當我們把代碼中的加運算重載函數修改成返回引用的時候:

Test& operator +(Test& temp2)//+運算符重載函數

{

Test result(this->a+temp2.a);

return result;

}

執行運算符重載函數返回引用將不産生臨時變量,外部的Test c=a+a; 將獲得一個局部的,棧空間內存地址位置上的值,而棧空間的特性告訴我們,當函數退出的時候函數體中局部對象的生命周期隨之結束,所以保存在該地址中的數據也將消失,當c對象去獲取存儲在這個地址中的值的時候,裏面的數據已經不存在,導致c獲得的是一個隨機值,所以作爲雙目運算的加運算符重載函數是不益采用返回引用方式編寫的,當然假如一定要返回引用,我們可以在堆內存中動態開辟空間存儲數據,但是這麽做會導致額外的系統開銷,同時也會讓程序更難讀懂。

對于遞增運算符來說,它的意義在于能夠改變自身,返回引用的函數是可以作爲左值參與運算的,所以作爲單目運算符,重載它的函數采用返回引用的方式編寫是最合適的。

假如我們修改遞增運算符重載函數爲值返回狀態的時候,又會出現什麽希奇的現象呢?

代碼如下:

Test operator ++()

{

return this->a++;

}

表面上是發現不出什麽非凡明顯的問題的,但是在main()函數中++(++c);的執行結果卻出乎意料,理論上應該是204的值,卻只是203,這是爲什麽呢?

因爲當函數是值返回狀態的時候括號內的++c返回的不是c本身而是臨時變量,用臨時變量參與括號外的++運算,當然c的值也就只改變了一次。結果爲203而不是204。

對于運算符重載函數來說,最後我們還要注重一個問題,當運算符重載函數的形式參數類型全部爲內部類型的時候,將不能重載

 
特别声明:以上内容(如有图片或视频亦包括在内)为网络用户发布,本站仅提供信息存储服务。
 
運算符重載是C++的重要組成部分,它可以讓程序更加的簡單易懂,簡單的運算符使用可以使複雜函數的理解更直觀。   對于普通對象來說我們很自然的會頻繁使用算數運算符讓他們參與計算,但是對于自定義類的對象來說,我們是無論如何也不能阻止寫出像下面的代碼一樣的程序來的。   例子如下: class Test { //過程省略 } int main() { Test a,c; c=a+a; } 當然這樣的代碼是不能夠通過編譯的,c++對自定類的算術運算部分保留給了程序員,這也是符合c++靈活特性的。   在c++中要想實現這樣的運算就必須自定義運算符重載函數,讓它來完整具體工作。   在這裏要提醒讀者的是,自定義類的運算符重載函數也是函數,你重載的一切運算符不會因爲是你自己定義的就改變其運算的優先級,自定義運算符的運算優先級同樣遵循與內部運算符一樣的順序。 [url=/bbs/detail_1783414.html][img]http://image.wangchao.net.cn/it/1323430136928.gif[/img][/url]   除此之外,c++也規定了一些運算符不能夠自定義重載,例如.、::、.*、.->、?:。   下面我們來學習如何重載運算符,運算符重載函數的形式是: 返回類型 Operator 運算符符號 (參數說明) { //函數體的內部實現 }   運算符重載函數的使用主要分爲兩種形式,一種是作爲類的友元函數進行使用,另一種則是作爲類的成員函數進行使用。   下面我們先看一下作爲類的友元函數使用的例子: //程序作者:管甯 //站點:www.cndev-lab.com //所有稿件均有版權,如要轉載,請務必聞名出處和作者 #include <iostream> using namespace std; class Test { public: Test(int a = 0) { Test::a = a; } friend Test operator +(Test&,Test&); friend Test& operator ++(Test&); public: int a; }; Test operator +(Test& temp1,Test& temp2)//+運算符重載函數 { //cout<<temp1.a<<"|"<<temp2.a<<endl;//在這裏可以觀察傳遞過來的引用對象的成員分量 Test result(temp1.a+temp2.a); return result; } Test& operator ++(Test& temp)//++運算符重載函數 { temp.a++; return temp; } int main() { Test a(100); Test c=a+a; cout<<c.a<<endl; c++; cout<<c.a<<endl; system("pause"); }   在例子中,我們對于自定義類Test來說,重載了加運算符與自動遞增運算符,重載的運算符完成了同類型對象的加運算和遞增運算過程 重載運算符函數返回類型和形式參數也是根據需要量進行調整的,下面我們來看一下修改後的加運算符重載函數。   代碼如下: //程序作者:管甯 //站點:www.cndev-lab.com //所有稿件均有版權,如要轉載,請務必聞名出處和作者 #include <iostream> using namespace std; class Test { public: Test(int a = 0) { Test::a = a; } friend Test operator +(Test&,const int&); public: int a; }; Test operator +(Test& temp1,const int& temp2)//+運算符重載函數 { Test result(temp1.a * temp2); return result; } int main() { Test a(100); Test c = a + 10; cout<<c.a<<endl; system("pause"); }   上面修改後的例子中,我們讓重載後的加運算符做的事情,事實上並不是同類型對象的加運算,而是自定義類對象與內置int常量對象的乘法運算。   值得注重的是,對于運算符重載來說,我們並不一定要用它一定要做同類型對象的加法或者是其它運算,運算符重載函數本身就是函數,那麽在函數體內部我們是可以做任何事情的,但是從不違反常規思維的角度來說,我們沒有必要讓重載加運算的函數來做與其重載的符號意義上完全不相符的工作,所以在使用重載運算符脫離原意之前,必須保證有足夠的理由。   下面我們討論一下作爲類成員函數的運算符重載函數的使用,及其函數的值返回與引用返回的差別。   下面我們先看實例,而後逐步分析。   代碼如下(重要部分做了具體的注解): //程序作者:管甯 //站點:www.cndev-lab.com //所有稿件均有版權,如要轉載,請務必聞名出處和作者 #include <iostream> using namespace std; class Test { public: Test(int a = 0) { Test::a = a; } Test(Test &temp) //運算符重載函數爲值返回的時候會産生臨時變量,臨時變量與局部變量result的複制會調用拷貝構造函數,臨時變量的生命周期是在拷貝構造函數運行完成後才結束,但假如運算符重載函數返回的是引用,那麽不會産生臨時變量,而局部變量result的生命周期在運算符重載函數退出後立即消失,它的生命周期要比臨時變量短,所以當外部對象獲取返回值的內存地址所存儲的值的時候,獲得是一個已經失去效果的內存地址中的值,在這裏的值返回與引用返回的對比,證實了臨時變量的生命周期比局部變量的生命周期稍長。 { cout<<"載入拷貝構造函數"<<"|"<<temp.a<<endl;//注重這裏,假如修改運算符重載函數爲返回引用,這裏就會出現異常,temp.a將獲得一個隨機值。 Test::a = temp.a; } ~Test()//在mian()內析構的過程是result局部變量産生的 { cout<<"載入析構函數!"<<endl; cin.get(); } Test operator +(Test& temp2)//+運算符重載函數 { //cout<<this->a<<endl; Test result(this->a+temp2.a); return result; } Test& operator ++()//++運算符重載函數 //遞增運算符是單目運算符,使用返回引用的運算符重載函數道理就在于它需要改變自身。 //在前面我們學習引用的單元中我們知道,返回引用的函數是可以作爲左值參與運算的,這一點也符合單目運算符的特點。 //假如把該函數改成返回值,而不是返回引用的話就破壞了單目預算改變自身的特點,程序中的++(++c)運算結束後輸出c.a,會發現對象c只做了一次遞增運算,原因在于,當函數是值返回狀態的時候括號內的++c返回的不是c本身而是臨時變量,用臨時變量參與括號外的++運算,當然c的值也就只改變了一次。 { this->a++; return *this; } public: int a; }; int main() { Test a(100); Test c=a+a; cout<<c.a<<endl; c++; cout<<c.a<<endl; ++c; cout<<c.a<<endl; ++(++c); cout<<c.a<<endl; system("pause"); }=版權所有 軟件 下載 學院 版權所有=   上例中運算符重載函數以類的成員函數方式出現,細心的讀者會發現加運算和遞增運算重載函數少了一個參數,這是爲什麽呢?   因爲當運算符重載函數以類成員函數身份出現的時候,C++會隱藏第一個參數,轉而取代的是一個this指針 接下來我們具體分析一下運算符重載函數的值返回與引用返回的差別。   當我們把代碼中的加運算重載函數修改成返回引用的時候: Test& operator +(Test& temp2)//+運算符重載函數 { Test result(this->a+temp2.a); return result; }   執行運算符重載函數返回引用將不産生臨時變量,外部的Test c=a+a; 將獲得一個局部的,棧空間內存地址位置上的值,而棧空間的特性告訴我們,當函數退出的時候函數體中局部對象的生命周期隨之結束,所以保存在該地址中的數據也將消失,當c對象去獲取存儲在這個地址中的值的時候,裏面的數據已經不存在,導致c獲得的是一個隨機值,所以作爲雙目運算的加運算符重載函數是不益采用返回引用方式編寫的,當然假如一定要返回引用,我們可以在堆內存中動態開辟空間存儲數據,但是這麽做會導致額外的系統開銷,同時也會讓程序更難讀懂。   對于遞增運算符來說,它的意義在于能夠改變自身,返回引用的函數是可以作爲左值參與運算的,所以作爲單目運算符,重載它的函數采用返回引用的方式編寫是最合適的。   假如我們修改遞增運算符重載函數爲值返回狀態的時候,又會出現什麽希奇的現象呢?   代碼如下: Test operator ++() { return this->a++; }   表面上是發現不出什麽非凡明顯的問題的,但是在main()函數中++(++c);的執行結果卻出乎意料,理論上應該是204的值,卻只是203,這是爲什麽呢?   因爲當函數是值返回狀態的時候括號內的++c返回的不是c本身而是臨時變量,用臨時變量參與括號外的++運算,當然c的值也就只改變了一次。結果爲203而不是204。   對于運算符重載函數來說,最後我們還要注重一個問題,當運算符重載函數的形式參數類型全部爲內部類型的時候,將不能重載
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有