乙個行為不同的物件產生出不同的形態這就是多型,多型也是實現**復用的方式那麼為什麼呢???
為什麼多型也是**復用的產物呢,因為多型的第乙個前提就是繼承,必須建立在繼承的基礎之上,才有多型之談,也就是說這個不同的物件也是有前提的,就是在繼承的條件之下的不同的類物件,簡單來說就是子類和基類
多型的第乙個條件就是呼叫的函式必須是虛函式,我們的派生類必須對基類的函式進行了重寫.
多型的第二個條件就是必須通過基類的指標或者引用去呼叫虛函式
重寫(也就是覆蓋)是在多型的前提之下,也就是說我們基類的函式進行了virtual的修飾,我們派生類在繼承了這個函式之後,自行定義了這個函式裡面的內容,這時候就構成了函式的重寫
當我們沒有對函式進行virtual關鍵字修飾,僅僅只是繼承,假如我們派生類中自行定義了乙個與基類重名的函式,這個時候,構成了同名隱藏
過載與多型是經常混在一起的概念,其實是不一樣的,函式過載建立在同乙個作用域裡面,我們的多型並沒有建立在同一作用域裡面,是在繼承的前提下那麼就是不同的類,過載是一種語言的特性,過載的實現是在編譯期間,我們的編譯器完成了對函式名字的重新修飾,這是在編譯期間就會去做的事情,是一種靜態的繫結,與多型的實現不同,多型的實現是在程式的執行期間,是一種動態的繫結.
結論就是:過載只是一種語言特性,與多型無關,與物件導向也無關!
多型的實現原理就是虛表,如果類中成員函式是加上了關鍵字virtual修飾的話,那麼生成的類中會多乙個位址,這個位址就是虛表指標,這個指標裡面存放的我們虛函式的函式位址,類似於繼承裡面的虛基表,在函式執行期間,如果構成了多型就會在這個表中去呼叫對應類的函式,從而完成各自呼叫各自函式的功能,也就實現了不同物件的同種行為的不同狀態;.
所以我們在實現多型的時候必須通過呼叫基類的指標或者引用來實現,為什麼不能呼叫派生類的物件或者引用呢,父類呼叫子類方法?子類是要搞特色的,父類能呼叫不合理假如這個時候你傳的是子類的引用,或者指標,但是父類物件中並沒有子類的實現函式,那麼不就存在不安全的事件了嗎?
普通函式的繼承是一種關於實現的繼承,我們可以使用繼承下來的函式,只不過這種行為側重的是繼承,
虛函式的繼承是一種介面的繼承,我們只是繼承了這個介面至於介面下面的內容,我們自己來實現,目的就是重寫函式,完成多型,
那麼,多型的作用是什麼呢?我們知道,封裝可以隱藏實現細節,使得**模組化;繼承可以擴充套件已存在的**模組(類);它們的目的都是為了——**重用。而多型則是為了實現另乙個目的——介面重用!而且現實往往是,要有效重用**很難,而真正最具有價值的重用是介面重用,因為「介面是公司最有價值的資源。設計介面比用一堆類來實現這個介面更費時間。而且介面需要耗費更昂貴的人力的時間。」
建構函式是不能進行虛函式修飾的,因為我們的虛函式指標是在建構函式初始化列表那裡生成的,所以是不行的]
內聯函式是不能用虛函式來修飾的,因為內聯函式在編譯期間,編譯器會將函式展開,函式並沒有位址,而我們多型是需要進行動態繫結的,由此可見是不行的
靜態函式也無法放進虛函式表中,因為我們的靜態函式並沒有this指標.
虛函式重寫的兩個意外
我們知道虛函式在進行重寫的時候,我們兩邊的函式必須是引數列表完全一致的,返回值型別也是一致的,但是如果返回值的型別是各自物件的指標或者引用的時候,這個時候我們叫協變,
我們基類的析構函式沒有加關鍵字修飾的時候,他也是會構成多型的,析構函式是清理物件空間的,那麼我想這個也是可以理解的.
在虛表的最後存著nullptr指標.
C 三大特性之多型
c 的三大特性,封裝,繼承,多型。封裝可以使得 模組化,繼承可以擴充套件已存在的 而多型的目的則是為了介面重用。本篇部落格主要介紹c 中多型的相關概念及使用方法。多型性是允許你將父物件設定成為和乙個或更多的他的子物件相等的技術,賦值之後,父物件就可以根據當前賦值給它的子物件的特性以不同的方式運作。簡...
java三大特性之多型
多型 多型的概述 1 多型 事物的多種狀態,polymorphic 物件的多型性 同乙個物件,可能具有不同的名稱,同乙個物件,有不同的型別的引用指向它。本質 同乙個物體有不同的名稱和描述。型別的多型性 同乙個型別,可能具有不同的子類實現。同乙個型別引用,有不同的物件實現。本質 同乙個名字和描述,可以...
OC的三大特性之多型
多型 1.沒有繼承就沒有多型 2.的體現 父類型別的指標指向子類物件 3.好處 如果函式 方法引數中使用的是父類型別,可以傳入父類 子類物件 4.侷限性 1 父類型別的變數 不能 直接呼叫子類特有的方法。必須強轉為子類型別變數後,才能直接呼叫子類特有的方法 import 動物 inte ce ani...