c++中執行時的多型性主要是通過虛函式來實現的,而編譯時的多型性是由函式過載和運算子過載來實現的。這一系列我將主要講解c++中有關運算子過載方面的內容。在每乙個系列講解之前,都會有它的一些基礎知識需要我們去理解。而運算子過載的基礎就是運算子過載函式。所以今天主要講的是運算子過載函式。
1.運算子過載是對已有的運算子賦予多重含義,使同乙個運算子作用域不同型別的資料導致不同行為的發生。比如
1inti;
2inti1=10,i2=10;
3i=i1+i2;
4std::cout<<"i1+i2="<
56doubled;
7doubled1=20,d2=20;
8d=d1+d2;
9std::cout<<"d1+d2="<
在這個程式裡"+"
既完成兩個整形數的加法運算,又完成了雙精度型的加法運算。為什麼同乙個運算子
"+"可以用於完成不同型別的資料的加法運算?這是因為
c++針對預定義基本資料型別已經對
"+"運算子做了適當的過載。在編譯程式編譯不同型別資料的加法表示式時,會自動呼叫相應型別的加法運算子過載函式。但是
c++中所提供的預定義的基本資料型別畢竟是有限的,在解決一些實際的問題時,往往需要使用者自定義資料型別。比如高中數學裡所提到的複數:
1classcomplex//複數類
211}
假如我們建立兩個複數,並用"+"
運算子讓它們直接相加:
1complexcom1(10,10),com2(20,20),sum;
2sum=com1+com2;
那麼會提示沒有與這些運算元匹配的"+"
運算子的錯誤。這是因為
complex
類型別不是預定義型別,系統沒用對該型別的資料進行加法運算子函式的過載。
c++就為運算子過載提供了一種方法,即運算子過載函式。其函式名字規定為operator後緊跟過載運算子。比如:operator+(),operator*()
等。現在我們給上述程式宣告乙個加法運算子的過載函式用於完成複數的加法運算:
viewcode
結果:在上述示例**中,呼叫運算子過載函式時,也可以以operator+(com1,com2)
的形式來呼叫,實際上
com1+com2
在程式解釋時也是轉化成前者一樣的形式。但是直接用
com1+com2
的形式更加符合人的書寫習慣。
2.上述示例中的運算子過載函式是不屬於任何的類,是全域性的函式。因為在
complex類(
複數類)
中的資料成員是公有的性質,所以運算子過載函式可以訪問。但如果定義為私有的呢,那該怎麼辦。其實,在實際的運算子過載函式宣告當中,要不定義其為要操作類的成員函式或類的友元函式。
(1)運算子過載函式作為類的友元函式的形式:
class
類名類外定義格式:
返回型別operator
運算子(
參數列)
友元函式過載雙目運算子(
有兩個運算元,通常在運算子的左右兩則
),參數列中的個數為兩個。若是過載單目運算子
(只有乙個運算元
),則參數列中只有一引數。
i.友元函式過載雙目運算子
(+):
viewcode
結果:ii.友元函式過載單目運算子
(++):
viewcode
結果:運算子過載函式可以返回任何型別,甚至是void
,但通常返回型別都與它所操作的類型別一樣,這樣可以使運算子使用在複雜的表示式中。比如把上述雙目運算子過載函式示例**中
main()
主函式裡的
com1+com2
改為com1+com2+com2
,那麼結果又會不一樣了。
像賦值運算子=
、下標運算子
、函式呼叫運算子
()等是不能被定義為友元運算子過載函式。同乙個運算子可以定義多個運算子過載函式來進行不同的操作。
(2)運算子過載函式作為類的成員函式的形式:
class
類名類外定義格式:
返回型別類名::operator
運算子(
形參表)
對於成員函式過載運算子而言,雙目運算子的參數列中僅有乙個引數,而單目則無引數。同樣的是過載,為什麼和友元函式在引數的個數上會有所區別的。原因在於友元函式,沒有this
指標。
i.成員函式過載雙目運算子
(+):
viewcode
對於雙目運算子而言,運算子過載函式的形參中僅為乙個引數,它作為運算子的右運算元(
如com2物件)
,而當前物件作為左運算元
(如:上述中的
com1物件)
,它是通過
this
指標隱含傳遞給成員運算子過載函式的。
ii.成員函式過載單目運算子
(++):
viewcode
對於單目運算子而言,當前物件作為運算子的運算元。
在運算子過載運用時應該注意以下幾個問題:(1)c++
中只能對已有的
c++運算子進行過載,不允許使用者自己定義新的運算子
;(2)c++
中絕大部分的運算子可過載,除了成員訪問運算子.,成員指標訪問運算子.*,作用域運算子::,長度運算子sizeof以及條件運算子?:;(3)過載後不能改變運算子的操作物件
(運算元
)的個數。如:
"+"是實現兩個運算元的運算子,過載後仍然為雙目運算子
;(4)
過載不能改變運算子原有的優先順序
;(5)
過載不能改變運算子原有結合的特性。比如:
z=x/y*a
,執行時是先做左結合的運算
x/y,過載後也是如此,不會變成先做右結合
y*a;(6)
運算子過載不能全部是
c++中預定義的基本資料,這樣做的目的是為了防止使用者修改用於基本型別資料的運算子性質
;(7)
從上述的示例中可以看到雙目運算子可以被過載為友元函式也可以過載為成員函式,但有一種情況,只能使用友元函式,是什麼情況呢?我舉個例子:
1classcomplex//複數類
212complexoperator+(intx);
13};
1415complexcomplex::operator+(intx)
1619
20intmain()
21如果我們把上述main()主函式實現部分裡的
total=com1+5
改為total=5+com1;那麼程式就會報錯(
沒有與這些運算元匹配的
"+"運算子
),因為左運算元
5不是該複數類的物件,不能呼叫相應的成員函式
complexoperator+(intx)
,所以編譯錯誤。但如果我們定義一下兩個友元函式就能解決上述的問題:
friendcomplexoperator+(complexcom1,intx);
friendcomplexoperator+(intx,complexcom1);
3.最後還是一樣,我將用乙個示例來總結一下今天所講的內容
(開發工具:
vs2010):
viewcode
結果:
mysql 函式過載 C 方法過載(函式過載)
在講解 c 構造方法 時提到定義構造方法時提到可以定義帶 0 到多個引數的構造方法,但構造方法的名稱必須是類名。實際上,這就是乙個典型的方法過載,即方法名稱相同 引數列表不同。引數列表不同主要體現在引數個數或引數的資料型別不同。在呼叫過載的方法時系統是根據所傳 遞引數的不同判斷呼叫的是哪個方法。例項...
C 函式 函式過載
如果同一作用域內的幾個函式名字相同但形參列表不同,我們稱之為過載函式。void print const char cp void print const int beg,const int end void print const int ia,size t size 這些函式接受的形參型別不一樣,...
C 函式過載
函式過載 overloaded function 在相同的作用域中的兩個函式,如果有相同的名字而形參表不同 注意 如果僅僅函式的返回值不同是不能實現函式過載 void func int int func int error,僅僅返回值不同是不能作為函式過載,這屬於函式重定義 形參表包括 引數的型別 ...