虛函式是實現c++多型性的關鍵。多型即「乙個介面多種方法」,通過虛函式的動態繫結技術,可以實現c++多型性。
多型性可以簡單地概括為「乙個介面,多種方法」,程式在執行時才決定呼叫的函式,它是物件導向程式設計領域的核心概念。多型(polymorphisn),字面意思多種形狀。
c++多型性是通過虛函式來實現的,虛函式允許子類重新定義成員函式,而子類重新定義父類的做法稱為覆蓋(override),或者稱為重寫。(這裡我覺得要補充,重寫的話可以有兩種,直接重寫成員函式和重寫虛函式,只有重寫了虛函式的才能算作是體現了c++多型性)而過載則是允許有多個同名的函式,而這些函式的引數列表不同,允許引數個數不同,引數型別不同,或者兩者都不同。編譯器會根據這些函式的不同列表,將同名的函式的名稱做修飾,從而生成一些不同名稱的預處理函式,來實現同名函式呼叫時的過載問題。但這並沒有體現多型性。
多型與非多型的實質區別就是函式位址是早繫結還是晚繫結。如果函式的呼叫,在編譯器編譯期間就可以確定函式的呼叫位址,並生產**,是靜態的,就是說位址是早繫結的。而如果函式呼叫的位址不能在編譯器期間確定,需要在執行時才確定,這就屬於晚繫結。
那麼多型的作用是什麼呢,封裝可以使得**模組化,繼承可以擴充套件已存在的**,他們的目的都是為了**重用。而多型的目的則是為了介面重用。也就是說,不論傳遞過來的究竟是那個類的物件,函式都能夠通過同乙個介面呼叫到適應各自物件的實現方法。
最常見的用法就是宣告基類的指標,利用該指標指向任意乙個子類物件,呼叫相應的虛函式,可以根據指向的子類的不同而實現不同的方法。如果沒有使用虛函式的話,即沒有利用c++多型性,則利用基類指標呼叫相應的函式的時候,將總被限制在基類函式本身,而無法呼叫到子類中被重寫過的函式。因為沒有多型性,函式呼叫的位址將是一定的,而固定的位址將始終呼叫到同乙個函式,這就無法實現乙個介面,多種方法的目的了。
虛函式用法:
適用的情況:如果只關注程式的行為,同事沒有繼承關係,那麼函式是否為虛函式根本無關緊要,只有當涉及到繼承的時候,才有必要考慮一些問題。
不適應的情況: l
虛函式代價不是很昂貴,可是也存在開銷,要考慮效率 l
有些情況下非虛函式能正確執行,而虛函式卻不行 l
不是所有類都是為了繼承而設計的
如果打算讓你的類支援繼承,那麼即使你不是使用其他虛函式,可能還是需要乙個虛析構函式。
只有當使用乙個基類指標或引用類指向或者引用乙個派生類物件時,虛函式和非虛函式之間才有區別。
需要虛析構函式的情況: l
有需要析構函式的事情發生。 l
它發生在這樣一種上下文中:指向乙個基類的指標或者引用都有乙個靜態型別,並且實際上都指向乙個派生類的物件。
因此,只有當使用指向基類的指標來刪除派生類的物件時,虛析構函式才有真正的意義。
如果需要乙個虛析構函式,定義乙個空的虛析構函式就行了。
總結為什麼虛析構函式不總是適用,有3個原因:其一是虛函式有時會帶來很大的開銷,其二是虛函式不總是提供所需的行為,其三是有時我們寫乙個類時,可能不想考慮派生問題。
另外,有一種情況必須適用虛函式:當你想刪除乙個表面上指向基類物件、實際卻是指向派生類物件的指標,就需要虛析構函式。
需要注意的是:只有通過引用或指標呼叫,虛函式才在執行時確定,只有在這些情況下,直到執行時才知道物件的動態型別。
靜態型別:static type,在編譯時可知的引用型別或者指標型別。
動態型別:dynamic type,指標或者引用多繫結的物件型別,這是僅在執行時可知。
C 什麼時候使用純虛函式
通常在實現乙個介面的時候使用純虛函式。介面一般就是乙個抽象類。有時在基類中將某一成員函式定為虛函式,並不是基類本身的要求,而是考慮到派生類的需要,在基類中預留乙個函式名,具體功能留給派生類根據需要去定義。例如,我們定義乙個point基類,point類中沒有求面積的area函式,因為點是沒有面積的。但...
什麼情況下應當宣告虛函式?純虛函式宣告
注意 只能用virtual宣告類的成員函式,使之成為虛函式,不能將類外的普通函式宣告為虛函式。因為虛函式的作用是允許在派生類中對基類的虛函式重新定義。所以只能用於類的繼承層次結構中。乙個成員函式被宣告為虛函式後,在同一類族中的類就不能再定義乙個非virtual的但與該虛函式具有相同的引數 包括個數和...
什麼時候使用 Lambda 函式?
python 中定義函式有兩種方法,一種是用常規方式 def 定義,函式要指定名字,第二種是用 lambda 定義,不需要指定名字,稱為 lambda 函式。lambda 函式又稱匿名函式,匿名函式就是沒有名字的函式,函式沒有名字也行?當然可以啦。有些函式如果只是臨時一用,而且它的業務邏輯也很簡單時...