什麼是多型
乙個介面,多種實現虛表指標是在什麼時候,或者什麼地方初始化呢?
答案:建構函式中進行虛表的建立和虛表指標的初始化,在構造子類物件時,1.要先呼叫父類的建構函式,此時編譯器只「看到了」父類,並不知道後面是否還有繼承者,它初始化父類物件的虛表指標,該虛表指標指向父類的虛表,2.當執行子類的建構函式時,子類物件的虛表指標被初始化,指向自身的虛表。多型分類(過載,重寫(覆蓋,虛函式))由於pfather實際指向的物件型別是son,因此vptr指向的son類的vtable,當呼叫pfather->son()時,根據虛表中的函式位址找到的就是son類的say()函式.
就是通過指標或引用才是動態繫結,通過點運算是不可以的。
靜態多型:過載。靜態多型是編譯器在編譯期間完成的,編譯器會根據實參型別來選擇呼叫合適的函式,如果有合適的函式可以呼叫就調,沒有的話就會發出警告或者報錯。函式過載動態多型:虛函式是。在執行期間。在基類的函式前加上virtual關鍵字,在派生類中重寫該函式,執行時將會根據物件的實際型別來呼叫相應的函式。如果物件型別是派生類,就呼叫派生類的函式;如果物件型別是基類,就呼叫基類的函式。
必須在同乙個類中進行函式重寫子類無法過載父類的函式,父類同名函式將被名稱覆蓋
過載是在編譯期間根據引數型別和個數決定函式呼叫
必須發生於父類與子類之間動態多型的條件並且父類與子類中的函式必須有完全相同的原型
使用virtual宣告之後能夠產生多型(如果不使用virtual,那叫重定義)
多型是在執行期間根據具體物件的型別決定函式呼叫
基類中必須包含虛函式,並且派生類中一定要對基類中的虛函式進行重寫。不能定義為虛函式通過基類物件的指標或者引用呼叫虛函式。
1)友元函式,它不是類的成員函式 2)全域性函式 3)靜態成員函式,它沒有this指標純虛函式(抽象類)4)建構函式,拷貝建構函式,以及賦值運算子過載(可以但是一般不建議作為虛函式)
在成員函式(必須為虛函式)的形參列表後面寫上=0,則成員函式為純虛函式。包含純虛函式的類叫做抽象類(也叫介面類),抽象類不能例項化出物件。純虛函式在派生類中重新定義以後,派生類才能例項化出物件。純虛函式是一定要被繼承的,否則它存在沒有任何意義派生類虛表
1.先將基類的虛表中的內容拷貝乙份多型缺陷2.如果派生類對基類中的虛函式進行重寫,使用派生類的虛函式替換相同偏移量位置的基類虛函式
3.如果派生類中新增加自己的虛函式,按照其在派生類中的宣告次序,放在上述虛函式之後
●降低了程式執行效率(多型需要去找虛表的位址)多型實現的三個條件●空間浪費
有繼承、有virtual重寫、有父類指標(引用)指向子類物件。多型的c++實現
virtual關鍵字,告訴編譯器這個函式要支援多型;不是根據指標型別判斷如何呼叫;而是要根據指標所指向的實際物件型別來判斷如何呼叫為什麼要定義虛析構函式(在什麼情況下應當宣告虛函式)
建構函式不能是虛函式。建立乙個派生類物件時,必須從類層次的根開始,沿著繼承路徑逐個呼叫基類的建構函式inliine函式可以實虛函式碼析構函式可以是虛的。虛析構函式用於指引 delete 運算子正確析構動態物件
不可以,因為inline函式沒有位址,無法將他存放到虛函式表中。建構函式可以是虛函式嗎
不可以,因為物件中的虛函式指標是在物件構造的時候初始化的。析構函式可以是虛函式嗎?什麼場景下析構函式是虛函式?
可以,最好將析構函式設定為虛函式,因為這樣可以避免記憶體洩漏的問題,如果乙個父類的指標指向了子類的的物件,如果子類物件中的虛函式沒有寫成多型的,他只會呼叫父類的析構函式,不會呼叫自己的析構函式,但是他建立物件的時候呼叫了建構函式,所以說就用子類的建構函式就應該該取呼叫他的析構函式,這樣才能保證所有的必須釋放的資源都是放了,才可以保證不會有記憶體洩漏。如果是多型的,就會先去呼叫子類的析構函式,然後再取呼叫父類的析構函式,這樣子類和父類的資源就都可以釋放。物件訪問普通函式快還是虛函式快?
如果是普通物件,是一樣快的,如果是指標物件或者是引用物件,呼叫普通函式更快一些,因為構成了多型,執行時呼叫虛函式要先到虛函式表中去查詢。這樣然後才拿到韓式的位址,這樣就不如直接可以拿到函式位址的普通函式快。虛函式表時再什麼階段生成的?他存放在**?
虛函式時在編譯階段生成的,他一般存放再**段,也就是常量區。虛函式表指標被編譯器初始化的過程怎麼理解的?
當類中宣告了虛函式是,編譯器會在類中生成乙個虛函式表vs中存放在**段,虛函式表實際上就是乙個存放虛函式指標的指標陣列,是由編譯器自動生成並維護的。虛表是屬於類的,不屬於某個具體的物件,乙個類中只需要有乙個虛表即可。同乙個類中的所有物件使用同乙個虛表,為了讓每個包含虛表的類的物件都擁有乙個虛表指標,編譯器在每個物件的頭新增了乙個指標,用來指向虛表,並且這個指標的值會自動被設定成指向類的虛表,每乙個virtaul函式的函式指標存放在虛表中,如果是單繼承,先將父類的虛表新增到子類的虛表中,然後子類再新增自己新增的虛函式指標,但是在vs編譯器中我們通常看不到新新增的虛函式指標,是編譯器故意將他們隱藏起來,如果是多繼承,在子類中新新增的虛函式指標會存放在第乙個繼承父類的虛函式表中。為什麼要引入抽象類和純虛函式?
為了方便使用多型特性,在很多情況下由基類生成物件是很不合理的,純虛函式在基類中是沒有定義的,要求在子類必須加以實現,這種包含了純虛函式的基類被稱為抽象類,不能被例項化,如果子類沒有實現純虛函式,那麼它他也是乙個抽象類。虛函式和純虛函式有什麼區別?
從基類的角度出發,如果乙個類中宣告了虛函式,這個函式是要在類中實現的,它的作用是為了能讓這個函式在他的子類中能被重寫,實現動態多型。純虛函式,只是乙個介面,乙個函式宣告,並沒有在宣告他的類中實現。對於子類來說它可以不重寫基類中的虛函式,但是他必須要將基類中的純虛函式實現。虛函式既繼承介面的同時也繼承了基類的實現,純虛函式關注的是介面的統一性,實現完全由子類來完成。什麼是多型?他有什麼作用?
多型就是乙個介面多種實現,多型是物件導向的三大特性之一。多型分為靜態多型和動態多型。靜態多型包含函式過載和泛型程式設計,程序多型是程式呼叫函式,編譯器決定使用哪個可執行的**塊。靜態多型是由繼承機制以及虛函實現的,通過指向派生類的基類指標或者引用,訪問派生類中同名重寫成員函式。類成員函式的過載、覆蓋和重寫區別多型的作用就是把不同子類物件都當作父類來看,可以遮蔽不同子類之間的差異,從而寫出通用的**,做出通用的程式設計,以適應需求的不斷變化。
過載和普通的函式過載一樣。覆蓋則基類的函式要加virtual (這就是多型的實現)
如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏,子類就重寫了這個函式
如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual關鍵字。此時,基類的函式被隱藏,子類就重寫了這個函式
總結 繼承,多型
一.不能被繼承的父類成員 1.private 2.子類與父類不在同包,使用預設訪問許可權的成員。3.構造方法。二.訪問許可權 從小到大 private 私有的 friendly 預設 protected 受保護的 public 公有的 三.方法重寫規則 1.方法名相同。2.引數列表相同。3.返回值型...
C 多型 繼承多型
什麼是多型?個人理解為 在程式語言繼承關係中,子類能替代父類,表現出不同的行為。換句話說 在繼承關係中,乙個類被例項化被其子類替代,子類中有父類的虛方法重寫,或者有父類同名方法 new 呼叫相同方法時候,將表現出子類或者父類中不同行為 老闆,上 static void main string arg...
c 課程總結3(繼承 多型)
一 繼承 繼承主要實現重用 節省開發時間。1 類繼承關係的語法形式 class 派生類名 基類名錶 2 繼承符合的規則 繼承是可傳遞的。如果c從b中派生,b又從a中派生,那麼c不僅繼承了b中宣告的成員,同 樣也繼承了a中的成員。派生類應當是對基類的擴充套件。派生類可以新增新的成員,但不能除去已經繼承...