本篇筆記主要分為兩個主要部分,第一部分關於對象模型,第二部分是關於new和delete的更加深入的學習。
在C中,對於不同的函數名采用靜態綁定的方法,每個函數直接對應了一個地址,存儲在相應的位置中。在C++中,非虛的成員函數也用靜態綁定的方式被存儲。如上圖中的A::func1()等成員函數。
不過對於虛函數,C++中采用了動態綁定的方法。在上圖中,每個虛函數都存儲在虛函數表中。當調用虛函數時,編譯器會隨著上圖中的路徑找到正確的函數調用。
由於動態綁定,不管什麼地方調用虛函數,總能得到正確的結果這個機制限制了虛函數應該被虛函數覆蓋。
虛函數可以由以下的兩種方式得到。
一個非常常用的基於虛函數的方式是建立一個指向抽象類的指針鏈表,這是多態的體現。
關於類的對象模型的內存分配,涉及到對象的位對齊的規則,在博客中的另一篇文章中有簡單介紹。
new和delete在使用時可以有一個可選的指針類型的參數,用來指定內存分配的起始地址。如果沒有這一參數,則會在堆空間中自動分配一段合適大小的空間。
默認的一個定位new函數是:
void* operator new(size_t size,void *start)
在使用時可以采用例如如下的方法:int *p = new(0x12345678) int;
事實上,我們還可以使用別的參數列進行new操作,我們也可以對operator new和operator delete進行重載。例如下面的兩個常用的參數列:
void* operator new(size_t size,long extra)//extra參數用於多申請一段存儲空間,專門用來存儲一些特別的信息,例如引用計數的信息。
void* operator new(size_t size,long extra,char init)
其固有的定義是:
inline void * operator new(size_t size){return malloc(size);}
inline void * operator new[](size_t size){return malloc(size);}//這裡在調用時size會自動進行計算。
inline void operator delete(void * ptr,size_t size){free(ptr);}
inline void operator delete[](void * ptr,size_t size){free(ptr);}
注意,如果需要進行重載,第一個參數始終應該是size_t格式的。此外,通常情況下自己定義的delete不會被調用,而是繼續采用默認的方法,直接釋放內存。只有當new操作失敗是,才會去尋找具有相同輸入參數列的operator delete函數;如果沒有定義相應的delete函數,也可以編譯通過,就代表放棄處理new失敗的這一異常。