-nonstatic member function設計準則:與一般非成員函式(nonmember function)有相同的執行效率。因此,實際上編譯器內部將nonstatic member 函式實體轉化為對等的nonmember 函式實體。
-轉換過程:
1. 新增額外this指標,提供資料訪問管道
2. 修改函式體內成員資料訪問方式,改為使用this指標訪問
3. 對函式名字重新「mangling」修飾處理
class a
int a::func() //nonstatic member function
int a::func(a *const
this) //1.新增額外引數this指標
int a::func(a *const
this) //2.改為由this指標訪問成員資料
extern
int func_1afv(a *const
this) //3.對函式名進行「mangling」修飾
obj.func() ---> func_1afv(&obj)
member function過載化,以提供獨一無二名稱,採用該手法。 函式
名稱+類
名稱+參
數數目+
引數型別
//可能的修飾方法:
int point::foo(float x) ---> int foo_5pointff(float x)
int point::foo(void) ---> int foo_5pointfv()
-靜態成員函式沒有this指標:
1. 不用直接訪問class中nonstatic members
2. 不能被宣告為const, volatile 或者virtual
3. 不需要有class object才能被呼叫
-static member function會被編譯器轉化為nonmember形式,實際上該類函式產不多等同於nonmember function。
static int a::func() //靜態成員函式
//各種方式呼叫靜態函式,均轉換成通過類作用於直接呼叫
ptr->func()/obj.func()/a::func() --> a::func()
//函式mangling修飾
a::func() ---> func_1asfv() //sfv表示靜態成員函式,引數void
//1是virtual table slot索引,關聯到func函式
ptr->func() -->(*ptr->vptr[1])(ptr)
//明確的呼叫可以抑制虛擬機制
a::func()
// 通過該obj呼叫不支援多型
obj.func() ---> func_1afv(&obj)
-通過class object呼叫virtual function的操作會被編譯器轉換為一般的nonmember member function,不呈現多型。
下面將虛函式的呼叫。
c++多型:以乙個public base class的指標,定址出乙個derived class object。
//呼叫虛函式,如何在執行期確定func()實體
ptr->func()
class point
virtual
float y() const //slot 3
virtual
float z() const //slot 4
protected:
point (float x = 0.0);
float _x;
}class point2d:public point //函式覆蓋 slot 3
protected:
float _y;
}class point3d:public point2d //函式覆蓋 slot 4
protected:
float _z;
}//一般來說我們事先並不知道ptr所指物件真正型別
//所以不知道哪個mult實體會被呼叫,但mult()固定在slot 2中是確定的
ptr->mult()
//因此編譯器如下轉換
//執行期唯一需要做的就是確定哪乙個slot 2的實體
//編譯時期就將指標轉移至第二個base class起始位址
base2 *pbase2 = new derived;
//執行時需要調整pbase2至derived起始位址
delete pbase2; //該行**無法在編譯時知道pbase2的真實物件,執行時才知道
-多重繼承結構如下:derived會有兩個vtbl被編譯器產生:(1)主體實體,與base1(最左端base class)共用 (2)次要實體,與base2有關
-三種需要調整指標的情況
1 通過指向base2的指標,呼叫derived class virtual function。
//編譯時期就將指標轉移至第二個base class起始位址
base2 *pbase2 = new derived;
//執行時需要調整pbase2至derived起始位址
delete pbase2;
2 通過指向derived class的指標,呼叫第二個base claass中的乙個繼承而來的virtual function。
//編譯時期就將指標轉移至第二個base class起始位址
derived *pder =
new derived;
//執行時需要調整pder以指向base2 subobject
pder->mumble; //呼叫base2::mumble()
3 三個clone函式實體返回值型別不同
//編譯時期就將指標轉移至第二個base class起始位址
base2 *pbase2 = new derived;
//呼叫derived* derived::clone()
//需要將pbase2指標調整至derived class起始處
//返回值時又需要重新調整至base2 subobject
base1 *pbase2_new = pbase2->clone;
-得到真實位址,但它需要繫結與某個class object上,才能通過它呼叫。
double (point::*coord) = &point::x;
//nonvirtual function
//呼叫函式
(obj.*coord) ()
//被編譯器轉化
(coord)(&obj) //&obj為this指標
-static member function函式位址為普通函式指標,因為沒有this指標。
class point
float (point::*pmf) = point::z; //= 2
point *ptr = new point2d;
ptr->*pmf;
//被編譯器轉化為
(*ptr->vptr[(int)pmf](ptr));
問題:如何區別member function指標指向位址還是virtual table索引?
方法:修改member function指標mptr結構體,mptr->index正負判別。
struct __mptr
}
深度探索C 物件模型
傳世經典書叢 深度探索c 物件模型 美 stanley b.lippman 斯坦利 b.李普曼 著 侯捷 譯 isbn978 7 121 14952 8 2012年1月出版 定價 69.00元 16開 356頁 宣傳語 如果你是一位c 程式設計師,渴望對於底層知識獲得乙個完整的了解,那麼本書正適合你...
深度探索C 物件模型
傳世經典書叢 深度探索c 物件模型 美 stanley b.lippman 斯坦利 b.李普曼 著 侯捷譯 isbn978 7 121 14952 8 2012年1月出版 定價 69.00元 16開 356頁 宣傳語 如果你是一位c 程式設計師,渴望對於底層知識獲得乙個完整的了解,那麼本書正適合你 ...
深度探索C 物件模型
深度探索c 物件模型 本書目錄結構如下 第1章 關於物件 object lessons 加上封裝後的布局成本 layout costs for adding encapsulation 1.1 c 模式模式 the c object model 簡單物件模型 a object model 驅動物件模...