繼承體系下同名成員函式的三種關係
- 過載
- 在同一作用域內
- 函式名相同,引數列表不同(分三種情況:引數個數不同,引數型別不同,引數個數和型別都不同)
- 返回值型別可以相同也可以不同
- 重寫(覆蓋)
- 在不同作用域內,分別在父類和子類
- 函式名相同,引數列表相同,返回值型別相同,協變除外(下面會介紹什麼是協變)
- 基類函式必須有virtual關鍵字修飾
- 父子類中函式的訪問修飾符可以不同
- 重定義(隱藏)
- 在不同的作用域內,分別是父類和子類
- 函式名相同
- 在基類和派生類中只要不構成重寫的都是重定義
過載
C++中函式過載達到的效果:
呼叫函式名相同的函式,根據實參的型別和個數選擇相應的實現函式體執行。
函式過載是一種靜態多型,或者稱之為靜態聯編、靜態繫結、靜態決議,其實都一樣。
重寫/覆蓋
在子類中定義一個與父類中完全相同的虛擬函式:
- 父類和子類中的虛擬函式,函式名、引數個數、引數型別以及返回值型別都相同,構成重寫。
- 子類中的虛擬函式與父類中的虛擬函式,函式名、引數個數和型別都相同,只是返回值不同,父類的虛擬函式返回父類的指標或引用,子類虛擬函式返回子類的指標或引用,這種情況下也構成重寫,我們稱之為協變。
C++中函式重寫達到的效果:
在子類中重寫了父類的虛擬函式,則子類物件呼叫該重寫函式時從子類內部呼叫,而不是從父類繼承,是一種動態多型。
在子類中重寫了父類的虛擬函式,如果用一個父類指標或引用指向子類物件,那麼該指標呼叫的是重寫的虛擬函式,也即是子類的虛擬函式, 而如果一個父類指標指向父類物件,則呼叫父類的虛擬函式。
重定義/隱藏
指的是在不同作用域內,函式名相同,但不構成重寫的則構成重定義。不僅僅是值類的成員函式,也可以是類的成員變數。
C++中重定義達到的效果:
如果再父類和子類中有相同名字的成員,子類中會將父類成員隱藏,此時無論在子類內部還是外部,通過子類成員會物件訪問該成員,訪問到的都是子類同名成員。
如果再子類內部或外部通過子類成員訪問同名成員函式,則需要根據函式呼叫的規則來呼叫子類的同名成員函式,否則呼叫失敗。