定義:類的成員函式前面加virtual關鍵字
虛函式重寫:子類定義了乙個與父類完全角同的虛函式,子類的函式重寫(覆蓋)父類的虛函式
隱藏:作用域不同,
注意:虛函式和虛繼承關鍵字一樣,但意義完全不同
多型:當使用基類的指標或引用呼叫重寫的虛函式時,當指向父類呼叫的就是父類的虛函式,指向子類呼叫的就是子類的虛函式
構成多型的條件:
1. 虛函式重寫
2. 必須是父類的指標或引用
呼叫原則:
如果構成多型,跟物件有關;不構成多型,跟型別有關
過載:在同一作用域中,函式名相同,引數列表不同,返回值可以不同
重定義/隱藏:在不同作用域中(分別在基類和派生類),函式名相同,在基類和派生類中只要不構成重寫就是重定義
重寫/覆蓋:在不同作用域中(分別在基類和派生類),函式名相同,引數相同,返回值相同(協變除外),基類函式必須有virtual關鍵字,訪問修飾符可以不同
總結:
1. 派生類重寫基類的虛函式實現多型,要求函式名、引數列表、返回值完全相同。(協變除外)
協變:如果是父類的指標或引用,返回值可以不同,也能構成多型
2. 基類中定義了虛函式,在派生類中該函式始終保持虛函式的特性。
3. 只有類的成員函式才能定義為虛函式。(和虛表有關)
4. 靜態成員函式不能定義為虛函式。
5. 如果在類外定義虛函式,只能在宣告函式時加virtual,類外定義函式時不能加virtual。
6. 建構函式不能為虛函式,雖然可以將operator=定義為虛函式,但是最好不要將operator=定義為虛函式,因為容易使用時容易引 起混淆。
7. 不要在建構函式和析構函式裡面呼叫虛函式,在建構函式和析構函式中,物件是不完整的,可能會發生未定義的行為。(父類呼叫建構函式可能會形成多型調到子類,先構造父類再構造子類,子類構造還沒有初始化)
8. 最好把基類的析構函式宣告為虛函式。(另外析構函式比較特殊,因為派生類的析構函式跟基類的析構函式名稱不一樣,但 是構成覆蓋,這裡是因為編譯器做了特殊處 理)
內聯函式不可以是虛函式,因為內聯函式沒有位址,會被展開;建構函式和靜態成員函式不可以是虛函式,因為靜態成員是共有的,定義成虛函式要放在虛表中,通過物件呼叫,靜態成員沒有this 指標。
乙個物件訪問普通成員和虛函式哪個更快?
不一定,如果虛函式構成多型的條件,訪問普通成員函式更快,否則一樣快。
在什麼情況下,析構函式需要定義成虛函式?
基類的析構函式,在不清理解決方案的情況下,可能會造成記憶體洩漏。
純虛函式:
在成員函式的形參後面寫上=0,則成員函式為純虛函式。包含純虛函式的類叫做抽象類(也叫介面類),抽象類不能例項化出物件。純虛 函式在派生類中重新定義以後,派生類才能例項化出物件。
友元與繼承:
友元關係不能繼承,也就是說基類友元不能訪問子類私有和保護成員。
繼承與靜態成員:
基類定義了static成員,則整個繼承體系裡面只有乙個這樣的成員。無論派生出多少個子類,都只有乙個static成員例項。
多型和虛函式
在c 中,多型是通過虛函式實現的。基類如果把乙個函式宣告為虛的 virtual 就表明繼承類可以覆蓋 override 這個函式 從而表現不同的行為,呈現出多型性 對於每乙個有虛函式的類,或者覆蓋了乙個或多個基類虛函式的繼承類,可認為有乙個與之關聯的虛函式表 v table v table 表中的每...
虛函式和多型
虛函式的概念 在類的成員函式前加virtual關鍵字,這個成員函式稱為虛函式。虛函式重寫 當在子類的定義了乙個與父類完全相同的虛函式時,則稱子類的這個函式重寫 也稱覆蓋 了父類的這個虛函式。include using namespace std class person public virtual...
虛函式和多型
pragma once 普通飛機 class plane include plane.h include using namespace std void plane fly void plane land pragma once include plane.h 直公升飛機 class jet pu...