第五章:純虛擬函式和聚合類的初始化
這一章講的東西很雜、所以我只歸納並延伸了一下標題提到的東西。比如這篇寫一下純虛擬函式和聚合類的構造。
一、純虛擬函式:
1.含有純虛擬函式的類不能有例項,所以一般純虛擬函式沒有定義。但是純虛還是是可以加上定義並且也能夠被呼叫的,但是必須滿足以下條件(結合了C++Primer的知識點)
①純虛擬函式的定義必須在類外。
②純虛擬函式的呼叫必須是靜態呼叫。即使用作用域限定符::,而不是使用 '->' 或 '.'呼叫符。最簡單的例子就是純虛的解構函式,因為派生類的解構函式會被編譯器器擴張以呼叫每一個上層的解構函式,所以需要抽象類定義純虛解構函式。
class vBase {public: virtual void test()=0; void foo(); } void vBase::test() { } void vBase::foo() { vBase::test(); }
2.《深度探索C++物件模型》中,因為如果基類中有純虛解構函式,則必須定義它,所以不建議將虛構函式設為純虛。而在《effective C++》中,如果沒有其餘純虛擬函式而編碼者卻希望構建一個抽象類,則可以將解構函式構造為純虛擬函式。兩者並不互斥。
二、聚合類
書中5.1講了無繼承情況下的物件構造,在討論如何給成員變數設定初值時,講了一個explicit initialization list要比建構函式的內聯擴張(inline expansion)效率更高。其實這個所謂的顯式初始化列表就是聚合類的列表初始化。
1.聚合類:①所有成員都是public。②沒有定義任何建構函式。③沒有類內初始值。④沒有基類也沒有虛擬函式
2.初始值列表:提供一個花括號括起來的成員初始值列表,初始值的順序必須和宣告順序一致
struct Data { int ival; string s; }
void foo()
{ Data val={0,"string"};
}
3.效率:當函式的activation record被放程序序堆疊時,初始化列表中的常量就可以被放進val的記憶體中了。至於這個activation record則是堆疊框架(stack frame)的另外一個名稱。在呼叫函式的時候被新增到呼叫棧,在函式返回的時候移除。它通常包含:被呼叫函式的地址,函式對呼叫者的返回地址,被呼叫函式的引數,先前的棧指標值。參考stackoverflow上面對他的解釋:
總結:就是聚合類的初始化列表效率比寫一個建構函式,然後讓編譯器對建構函式進行擴充套件的效率要高。