C的對像模型基於編譯時和運行時機制的組合,以支持繼承,多態性和封裝等特徵。從本質上講,它依靠班級的概念作為創建對象的藍圖。每個對像都是類的實例,其中同時包含數據(成員變量)和代碼(成員函數)。
繼承:繼承允許基於現有的(基礎類)創建新類(派生類)。派生的類繼承其基類的成員(數據和功能),可以添加自己的成員或覆蓋現有成員。這促進了代碼重用並建立“ IS-A”關係。例如, Dog
課可能會從Animal
階級繼承。
虛擬函數:虛擬函數是基類中使用virtual
關鍵字聲明的成員函數。它們啟用運行時多態性,這意味著要調用的正確函數是根據對象的實際類型在運行時確定的,而不是其聲明的類型。這對於實現靈活性和可擴展性至關重要。它背後的機制是虛擬函數表(VTable) 。每個具有虛擬函數的類都有其自己的VTable,這是該類中實現的虛擬函數的指針表。包含虛擬函數的類的每個對像都有一個隱藏的指針(通常稱為VPTR),指向其類的VTable。當調用虛擬函數時,運行時使用VPTR在VTable中找到正確的函數。
例子:
<code class="c ">class Animal { public: virtual void makeSound() { std::cout makeSound(); // Calls Dog::makeSound() due to virtual function delete animal; return 0; }</code>
在此示例中, makeSound
是虛擬函數。即使將animal
宣佈為Animal
指針,但由於可VT的機制,在運行時(從Dog
類類中)的正確makeSound
功能也被調用。
與非虛擬函數相比,使用虛擬函數引入了性能開銷。這個高架源於幾個因素:
但是,這些開銷通常很小,通常可以忽略不計,尤其是與虛擬功能提供的多態性和代碼可維護性的好處相比。現代編譯器採用各種優化技術來最大程度地降低虛擬功能的性能影響,例如內部和功能指針緩存。只有在代碼的性能 - 關鍵性段中調用虛擬函數時,性能影響才有意義,即使這樣,除非函數被稱為大量次數,否則差異通常是邊緣的。
C繼承以多種方式影響內存管理和對像大小:
unique_ptr
, shared_ptr
)可以簡化內存管理。靜態調度和動態調度是確定在運行時要調用哪種功能的兩種不同的方法。關鍵區別在於做出決定時:
說明區別的示例:
<code class="c ">class Animal { public: void makeSound() { std::cout makeSound(); // Static dispatch: Calls Animal::makeSound() animal->move(); // Dynamic dispatch: Calls Dog::move() delete animal; return 0; }</code>
在此示例中, makeSound
使用靜態調度,因為它不是虛擬的,而move
使用動態調度,因為它是虛擬的。這表明了virtual
關鍵字的存在(或不存在)如何決定調度機制。
以上是C的對像模型如何工作,包括虛擬函數和繼承?的詳細內容。更多資訊請關注PHP中文網其他相關文章!