概要:
c++中經常出現函式名字一樣,但引數列表或返回值不同的函式,要搞清楚函式的正確呼叫關係,需理清三個概念:重寫(override)、過載(overload)、重定義(redefine)。
一、三個基本概念
1、重定義(redefine):派生類對基類的成員函式重新定義,即派生類定義了某個函式,該函式的名字與基類中的函式名字一樣。
特點:(1)不在同乙個作用域(分別位於基類、派生類) (2)函式的名字必須相同 (3)對函式的返回值、形參列表無要求
特殊情況:若派生類定義的該函式與基類的成員函式完全一樣(返回值、形參列表均相同),且基類的該函式為virtual,則屬於派生類重寫基類的虛函式。
作用效果:若重新定義了基類中的乙個過載函式,則在派生類中,基類中該名字的函式(即其他所有過載版本)都被自動隱藏,包括同名的虛函式。
2、過載(overload):函式名字相同,但它的形參個數或者順序,或者型別不同,但是不能靠返回型別來判斷。
特點:(1)位於同乙個類中 (2)函式的名字必須相同 (3)形參列表不同(可能是引數個數 or 型別 or 順序 不同),返回值無要求
特殊情況:若某乙個過載版本的函式前面有virtual修飾,則表示它是虛函式。但它也是屬於過載的乙個版本
不同的建構函式(無參構造、有參構造、拷貝構造)是過載的應用
作用效果和原理:編譯器根據函式不同的參數列,將函式體與函式呼叫進行早繫結。過載與多型無關,只是一種語言特性,與物件導向無關。
3、重寫(override):派生類重定義基類的虛函式,即會覆蓋基類的虛函式 (多型性)
特點:(1)不在同乙個作用域(分別位於基類、派生類) (2)函式名、形參列表、返回值相同 (3)基類的函式是virtual
特殊情況:若派生類重寫的虛函式屬於乙個過載版本,則該重寫的函式會隱藏基類中與虛函式同名的其他函式。
作用效果:父類的指標或引用根據傳遞給它的子類位址或引用,動態地呼叫屬於子類的該函式。這個晚繫結過程只對virtual函式起作用
具體原理是由虛函式表(vtable)決定的,在第三節介紹。
二、程式例項
1、兩個類:基類( 取名test)和派生類( 取名xx) 名字不規範,哈哈隨便取得!
分析:基類class test中定義了名為f的3個過載函式,其中最後乙個是虛函式
派生類class xx中對f進行了重定義,所以會隱藏基類中名為f的版本。其中派生類的double f(int dataa,int datab)屬於對虛函式的重寫
分析:(1)test 1中進行了過載測試,根據傳遞引數的不一樣,呼叫不同的函式 (早繫結,與多型無關)
(2)test 2中test b = d;定義了乙個基類物件,用派生類物件來進行初始化。這會呼叫基類的拷貝建構函式,生成基類的物件b,基類的拷貝建構函式初始化b的vptr,指向b的vtable。因此所有的函式呼叫都只發生在基類,不會產生多型。
這是乙個物件切片過程(參見《c++程式設計思想.第二版》p370),物件切片是當它拷貝到乙個新的物件時,會去掉原來物件的一部分,而不是像使用指標或引用那樣簡單地改變位址的內容。
(3)test 3和test 4中,定義的基類指標和引用,故會發生多型。
三、晚繫結原理:虛函式表
編譯器會對每乙個包含虛函式的類(或者從包含虛函式的基類派生的類)建立乙個表(vtable),裡面存放特定類的虛函式的位址。然後編譯器秘密地放置一指標vpointer(vptr),指向這個物件的vtable。當通過基類指標做虛函式呼叫時(即多型呼叫時),編譯器靜態地插入能取得這個vptr並在vtable表中查詢函式位址的**,這樣就能呼叫正確的函式並引起晚繫結的發生。
這個具體過程, 可以參見本人的另一篇部落格《c模擬實現c++的多型
》(完)
C 函式的過載 重寫 隱藏
過載 1 在同一作用域中。2 函式名相同 引數個數或引數型別不同。3 過載又稱為靜態多型,靜態繫結,靜態決議等。因為要實現過載,所以c 和c的命名方式有所不同。過載主要是為了減輕程式設計師對函式名的記憶負擔,讓所有功能相似的函式使用同一名字。4 任何程式都僅有乙個 main 函式的例項。main 函...
C 的過載 重寫 隱藏
在同乙個class中 class demo 在同一訪問區內 如在同一.c cpp檔案內 即不在struct或者class中 4個fun都是過載函式 intfun int a void fun double a int fun int a,int b int fun float a 父類 class ...
C 函式的過載 重寫與隱藏
1 幾個概念與區別 1 函式重寫 也稱作覆蓋,是用於類的繼承中,函式名 引數個數 型別都相同,僅函式體不同。2 函式過載 是指同一作用域的不同函式使用相同的函式名,但是引數個數或型別不同。3 函式隱藏 既不是過載也不是重寫,例如 函式名及引數完全相同卻又不是虛函式,卻在子類中重新實現該函式,也就是所...