brew介面的繼承和多型
李振鵬brew
平台支援c 和
c++ 開發語言,而
c 語言是不支援物件導向的,只有
c++ 支援物件導向的程式設計,因此
brew
中必須使用
c 語言模擬實現
c++ 語言物件導向機制。在
c++ 中繼承是基於
c++ 記憶體中資料是按照一定順序排列的,而
c++ 的多型是基於虛函式表機制的。通過具體物件實現替換虛函式表中某些函式項的位置實現多型。 c
結構體中記憶體物件的布局是採用按照定義順序排列的,也就是採用如下的方式:
如果結構體定義如下:
struct a ;
在記憶體中的各個程式的布局如圖所示:
int a;
int b;
int c 圖
1
記憶體中資料的排列
而如果結構體的定義如下:
struct b ;
在記憶體中的布局如圖所示:
int a;
int b;
int c;
int d 圖
2
增加成員後記憶體中資料的排列
這樣可以看出完全是按照定義的順序布局的,而如果採用如下的方式定義結構體c :
struct c ;
其在記憶體中的布局如下圖所示:
struct a
int d 圖
3
含有結構體成員的記憶體布局
這樣結構體成員
a 在記憶體中的布局如圖
1 所示,如果把
a 全部展開,就與結構體
b 的記憶體布局圖
2 相同,這樣如果訪問結構體
c 中的
a 的成員
a ,雖然採用
c.a.a
才可以,但是記憶體中的布局與直接訪問
a.a 效果是相同的,只不過增加了乙個編譯中間層,因此,在
brew
中可以依照此技術實現繼承機制。而把父結構體當作子結構體的第乙個成員變數時,可以在執行時通過使用父結構的成員訪問方式直接訪問實際子結構體的成員變數,並且可以使用型別轉換,轉換為實際的子結構體,這樣的技術正好是物件導向程式設計中繼承和多型技術的基礎。
而物件導向技術中的關鍵技術多型是基於以上的記憶體模型和函式指標實現的,一般來說,如果使用類
c 語言描述多型,它相當於增加了乙個間接層,在這個間接層攔截對於方法的呼叫,然後根據具體的指標指向實際物件呼叫相應的方法實現。必須完成如下的步驟: (
1 )獲知方法呼叫的全部資訊,包括呼叫的是哪個方法,傳入的實際引數有哪些; (
2 )獲知呼叫時指標所指向的實際物件; (
3 )根據(
1 ),(
2 )所獲得的資訊,找到合適的實現**,執行呼叫。
從上面的步驟可以看出,應該根據怎樣進行資訊進行方法的查詢,一般來說,有兩種思路:
一種是根據方法的名稱進行查詢,通過比較字串的方式進行查詢,因此效率較差,但是由於字串具有唯一性,因此不必為了對齊,而浪費空間,占用空間小;
另一種方法是基於絕對位置的定位技術,其查詢結構十分的簡單,只由乙個存有方法位址的指標陣列,也就是通常說的虛函式表,這種方法速度快,只需要進行一次簡單的位址相加就可以了,但缺點是不管派生類有多少項需要更改的基類虛函式,都必須擁有和基類相同大小的虛函式表,因此浪費了空間,這種方式執行速度極快,並且是
c++ 語言所採用的技術,因此基於速度考慮,同時為了相容
c/c++
語言開發,
brew
採用這種模型。
在介面中定義大量的函式指標,並且
brew
規定所有
brew
的模組必須實現
ibase
介面,而
ibase
介面的實質為如下的定義:
struct ibase ;
為了能夠順利從
ibase
介面派生特別定義了巨集
inherit_ibase
,它其實就是如上的介面定義,而且
brew
的定義模型,為了防止在介面之間轉換造成混亂,只支援單根繼承,也就是說使用者每次只能夠從乙個介面派生,並不能同時派生多個介面,派生時使用如下的方式:
struct iinherit ;
這樣根據上文介紹的記憶體模型,可以使用
ibase
介面來訪問他的成員,而實際上訪問的是
iinherit
介面的成員。
但是這樣只是定義了介面,並沒有具體的實現,可以再另外定義新的結構體,以此介面的成員函式指標作為結構體的第乙個成員變數,這種記憶體布局方式,與
c++ 中單繼承的虛函式表的記憶體布局方式相同,並且這第乙個指向介面的成員就是虛函式表。具體定義如下所示:
struct iinherit_class ;
這樣就可以根據上文介紹的記憶體對映技術,使用
iinherit
的介面訪問
iinherit_class
的成員,而且只通過
iinherit
介面並無法訪問實際的資料成員,這樣就達到了資料封裝的效果。
但是對於這個所謂的虛函式表,與
c++ 中不同的是必須由使用者進行初始化,編譯器並不會初始化,因此要給介面成員分配記憶體,並且使函式指標指向實際的函式位址。並且根據不同的實現類指向不同的實現函式,這樣執行時就可以只根據介面訪問呼叫實際指向的物件的方法,從而實現執行時的多型。
介面的多型
多型 必須得有繼承,而且父類的指標指向子類的物件就叫多型 介面 介面也叫類,不過它不是用class類修飾類名的,而是用inte ce關鍵字來修飾類名的,它沒有構造方法,有屬性,有普通方法,不過這個普通方法在編譯器中是用abstract關鍵字修飾的抽象類,並且這個抽象方法只能被用作某個類的實現重寫,而...
介面的多型
public iterator elements 這裡的iterator 是介面,但是突然很疑惑,介面怎麼能宣告方法呢。後面查詢發現 這個介面 iterator 的實現類有很多,如果返回的型別是linkedlistiterater,的話就只能返回這乙個型別,這樣的話太侷限了.返回的型別 iterat...
Java核心 介面 繼承和多型 多型
利用多型可以使程式具有良好的擴充套件性,並可以對所有類物件進行通用的處理。eg 定義乙個平行四邊形的類 parallelogram 在類中頂乙個 draw 方法。public class parallelogram 如果需要頂乙個繪製正方形的方法,通過定義乙個正方形類來處理正方形物件,會出現 冗餘的...