看到章節名以後聯想第二章,和自己想的差不多。這張主要是更細化講解,具體的「擴充」過程
不要把虛析構定義為pure。這個和google程式設計規範裡寫得一樣,介面類應該全都是純虛函式及乙個虛析構函式,不應具有建構函式。
不要指望編譯器去識別沒有有派生類重寫虛函式而主動去掉virtual,應自己決定好是否有virtual
虛函式不要有const
析構函式的建立並不是見到「virtual」就會自動建立,和構造不一樣,只有在成員物件或基類有析構時才會被建立出來,也就是構造和析構不一定會成對出現,非必要時不要自己建立析構。
plain ol』 data,c風格的struct結構體定義的資料結構,編譯器不會對此型別新增構造和析構、拷貝函式(會用位拷貝代替)。與c的區別,對於全域性變數c認為是臨時性定義,而c++認為都是初始化過的資料。
全域性物件程式啟動時初始化,結束時銷毀
當所有資料成員都為public時,可以通過point p = ;方式構建同時初始化(顯示初始化列表),其對應值只能為常量(編譯時確定值)。
當我們定義乙個object如:t object;如果t有乙個constructor(不管是trival還是nontrival),它都會被呼叫,constructor呼叫伴隨了(下面按擴充後**的順序寫得):
有virtual base class,虛基類的建構函式必須被呼叫,從左往右,從深往淺:
類如果在成員初始化列表中,則顯式指定的引數都應該傳過去,不在初始化列表中的類,呼叫其預設建構函式
類中每乙個虛基類子物件(subobject)的偏移位置(offset)必須在執行期是可取的
類物件是最底層的派生類,其建構函式可能被呼叫,用以支援這一行為的機制需要被執行
有base class,基類的建構函式必須被呼叫,以base class宣告順序為順序;
如果基類在初始化列表中顯式指定,那麼任何顯式指定的引數都應該傳進去
如果基類不在初始化列表中,但有預設建構函式的話,那麼就呼叫這個預設建構函式構造基類
如果基類是多重繼承下的第二或後繼的基類,那麼this指標要做調整
如果類物件有虛表指標,初始化指向適當的虛函式表
函式初始化列表中的成員變數的初始化操作會被放入建構函式中
如果有成員不在初始化列表中,並且其有預設建構函式,那麼預設建構函式必須被呼叫
虛擬繼承涉及到virtual base subobject共享性,不能重複構建,針對上面的第一步,進行擴充時要特別處理。
會對每乙個虛基類增加乙個識別符號(__most_devried)是否有多個派生類,當第一次構建時為false進行構建,並改為true,後續再遇到構建時將不再重複構建。同樣的針對析構函式也要做處理,避免重複釋放。實際上就是繼承鏈的最底層派生類負責對虛擬基類的object的構建,中間層不會進行重複構建。
上面的方式會增加過多的判斷,為了增加這些判斷編譯器的**會更加複雜,因此有些新的編譯器針對建構函式分成兩份,乙個完整object,乙個針對subobject。完整的無條件呼叫所有virtual base構造,subobject不呼叫任何虛擬基類構造。
對於vptr的指定:在base class constructiors呼叫操作之後,在程式設計師**或初始化列表中所列的成員初始化操作之前,此時將vptr指向對應的vtbl
乙個類對於預設的拷貝運算子函(=號)數,在以下情況,不會表現出按位拷貝的語意。
當類中含乙個成員物件,而這個object的class有乙個賦值運算子函式
當類的基類有乙個賦值運算子函式
當乙個類宣告了任何虛函式,這時候不可以拷貝右邊類物件的vptr,因為其可能是派生類物件
類繼承自虛基類,不論這個base class是否有拷貝函式
效能上來說,在虛擬繼承時,可以保證虛擬基類拷貝後只有乙個subobject,但並未要求這個subobject只被指派一次內容(初始化一次),也就是拷貝過程中虛擬基類會被多次初始化,因為多個派生類的「=」操作均會被執行,(如其int成員會被多次賦值為0),只影響初始化,subobject不會重複。
只有在member object或base class擁有析構時,編譯器才會合成出乙個,否則不會被合成也不會被呼叫(delete時不會執行操作),單純自身擁有虛函式是不會建立析構函式的。
構造與析構不一定要成對
析構函式的執行順序一般是
析構函式的函式本體首先被執行
如果類有類物件成員,而類物件有析構函式,那麼他們會以其宣告順序的相反順序被呼叫
如果物件內含有乙個vptr,現在被重新設定,指向適當的基類的虛函式表(也就是在虛函式中程式設計師縮寫**之前vptr已經被重新指向為基類了)
如果有上一層的非虛基類有析構函式,那麼會以宣告順序相反的順序執行
如果有任何虛基類有析構函式,且當前類是繼承鏈的最底層派生類,那麼它們會以原來構造順序的相反順序被呼叫
coologic 部落格網域名稱已更改,已從 www.techieliang.com 改為
www.coologic.cn,上述鏈結位址受到影響,若需檢視源文請手動修改,多有不便,敬請諒解。
《深度探索C 物件模型》讀書筆記(5)
純虛函式 在設計抽象基類時,需要注意以下幾點 1 不要將destructor宣告為pure virtual function 如果將destructor宣告為pure virtual function,則設計者一定得定義它。因為每乙個derived class destructor會被編譯器加以擴充...
《深度探索C 物件模型》讀書筆記(5)
純虛函式 在設計抽象基類時,需要注意以下幾點 1 不要將destructor宣告為pure virtual function 如果將destructor宣告為pure virtual function,則設計者一定得定義它。因為每乙個derived class destructor會被編譯器加以擴充...
深度探索C 物件模型之C 物件模型筆記
0.菜鳥覺得,在看這本書的時候最好切換角色,把自己的思維轉換成編譯器開發者,去考慮問題,這樣會容易理解些.當然這樣很難,就想著自己要解決什麼樣的問題好了 1.在c 中,類的資料成員有兩種 靜態和非靜態 成員函式有三種 靜態,非靜態 虛函式。之所以這樣分,大概是因為在設計c 物件模型時,非靜態的資料成...