Chapter 4.? The Semantics of Function: Function 語意學
4.1 Member 函數的各種調用方式
1. Nonstatic Member Function(非靜態成員函數)
??? 要做如下的轉換:
??? (1) 改寫函數的原形, 安插一個參數到member function中, 用于提供一個存取管道, 使class object 得以調用該函數, 這個額外的指針稱之為: this指針.
??? 如:??
?Point3d::magnitude()? 會轉換為:? Point3d::magnitude(Point3d *const? this)
??? (2)? 對函數內每一個針對nostatic data member的存取操作改經由this指針來存取.
???? 如:
?????????? return sqrt(
??this->_x? *? this->_x? + this->y * this->_y? + this->_z * this->_z;
??? (3)? 將對member function 重寫一個外部函數, 對函數名稱進行"mangling"處理, 使它生成一個獨一無二的名稱
???
2. Virtual Member Function(虛擬成員函數)
???? 例如:
? ptr->normalize();
? 它將被轉化為如下的調用:
?( * ptr->vptr[ 1 ])( ptr );
?這里有幾點說明:
?i.? vptr是由編譯器生成的指針,指向virtual table
?ii.? 1 這里是virtual table slot 的索引值,它關聯到nomalize這個函數
?iii.? 第二個ptr表示this指針
3. Static Member Function(靜態成員函數)
???? 如果Point3d::normalize()是一個static member function的話,這兩個調用會轉化為一般的操作:
???? obj.normalize();
???? ptr->normalize();
???? 轉化為:
???? // obj.normalize();
???? normalize__7Point3dSFv();
???? // ptr->normalize();
???? normalize__7Point3dSfv();
4.2 Virtual Member Functions(虛擬成員函數)
1. 單一繼承下的Virtual Functions
???? 一個多態的class object 身上增加兩個members:
?I.?? 一個字符串或數字,? 表示class的類型
?II.? 一個指針,指向某個表格,表格中帶有程序的virtual function的執行時期地址
??? 對于一個active virtual function包括下面三個內容:
??????? I.?? 這個class 所定義的函數實體, 它會改寫一個可能存在的base class virtual function 函數實體.
?II.? 繼承自基類的實體, 這是在derived class 決定不改寫virtual function 時才會出現的情況
?III. 一個pure_virtual_called()函數實體,它既可以扮演pur virtual function的空間保衛者角色, 也可以當做執行期異常函數.
2. 多重繼承下的Virtual Functions
??? 這種繼承涉及到要調整this指針,并且要求不止一個vtbl和vptr,同時要好幾個這種虛表和指針
3. 虛擬繼承下的Virtual Functions
4.3 函數的效能
4.4 指向Member Functions的指針(Pointer-to-Member Functions)
1. 指向一般成員函數的指針(Nostatic member and novirtual member function)
??? 取一個nostatic member function的地址,? 如果該函數是novirtual, 則得到的結果是它在內存中真正的地址, 然而這個地址也不是完全的, 它也需要綁定到某個class object的地址上, 才能夠調用該函數. 所有的nostatic member functions都要對象的地址(用this指出).
??? 例如:
???? double (Point::*pmf)();?// 定義一個成員函數指針
????? pfm = &Point::y;???// 初始化這個指針為
???? (ptr->*pfm)() ;???// 調用為,? 編譯器轉化為: (pfm)(ptr)
2. 支持"指向Virtual Member Functions"的指針
??? 對于virtual function, 其地址在編譯時期是未知的, 所能知道的僅是virtual function在相關的vitual table 中的索引值. 也就是說對于一個virtual member function取其地址, 所能獲得的只是一個索引值.
??? 所以如果:
??? pmf = &Point::z();?// 獲得的是索引值,? 調用時:
??? (ptr.->pmf)()???// 會轉化為: (* ptr->vptr[(int)pfm] (ptr)
3. 在多重繼承下,指向Member Functions的指針
???? 比較復雜,? 定義了一個結構支持這們的操作
4. 指向 Member Functions 指針的效率
4.4 Inline Functions
1. inline functions的生成條件
2. 對形式參數的處理(Formal Arguments)
例如:
?1?inline?int?min(?int?i,?int?j?)?
?2??{?
?3?????return?i?<?j???i?:?j;?
?4??}?
?5??and?the?following?three?invocations?of?the?inline?function:
?6?
?7??inline?int?bar()?
?8??{?
?9?????int?minval;?
10?????int?val1?=?1024;?
11?????int?val2?=?2048;?
12?
13??/*(1)*/minval?=?min(?val1,?val2?);?
14??/*(2)*/minval?=?min(?1024,?2048?);?
15??/*(3)*/minval?=?min(?foo(),?bar()+1?);?
16?
17?????return?minval;?
18??}?
?
用下面的方式進行處理:
?? (1)? 直接的參數替換
?//(1)???? simple argument substitution
?minval = val1 < val2 ? val1 : val2;
?? (2) 如果實際參數是一個常量表達式(const expression),? 我們就可以在替換前完成對它的求值操作.
?//(2)? constant folding following substitution
?minval = 1024;
??
?? (3) 帶有副作用的實際參數, 引入臨時性的對象
?//(3)???? side-effects and introduction of temporary
?int t1;
?int t2;
?minval =? ( t1 = foo() ), ( t2 = bar() + 1 ),? t1 < t2 ? t1 : t2;
3. 對inline函數帶有局部變量的處理(Local Variables)
??? 如:
?inline int min( int i, int j )
?{
??int minval = i < j ? i : j;
??return minval;
?}
??? 對于如下的調用:
??? {
??? int local_var;
??? int minval;
??? // ...
??? minval = min( val1, val2 );
???? }
??? 轉換可能的結果是:
1?????{?
2?????int?local_var;?
3?????int?minval;?
4?????//?mangled?inline?local?variable?
5?????int?__min_lv_minval;?
6?
7?????minval?=??(?__min_lv_minval?=??val1?<?val2???val1?:?val2?),??__min_lv_minval;?
8??????}
?