在前面文章《C++對象模型》可以知道,class 中成員函數的類型有:nonstatic member function、static member function、virtual member function;不同類型的成員函數的調用會有不同的表現,以下對每種類型的成員函數進行簡單的分析。
為了使 nonstatic member function 能夠與非成員函數具有相同的效力,C++ 編譯器內部將 nonstatic member function 轉換為非成員函數,轉換的步驟以下:
例如:
class example{
public:
void func();
};
/* 其中成員函數 func() 會被編譯器內部轉換為 void func(example *this)*/
Static member function 和 nonstatic member function 1樣會被編譯器內部轉換為非成員函數,區分是轉換后不存在 this 指針,因此和全局函數1樣,可以做 callback 函數。Static member function 有以下的特性:
在獨立的 class 中 virtual member function 的調用有兩種方式:指針調用 和 對象調用。例如:
class A {
virtual void func();
};
A a;
A *pA;
a.func();
pA->func();
用指針調用pA->func()
在編譯器內部被轉換為( * pA->vptr[1])(pA)
;
用對象調用 a.func()
在內部被當作和非虛擬成員函數1樣處理,即轉換為A::func(&a)
;所以 virtual 可以inline,在用對象調用的情況下inline 被展開。
具有 virtual member function 的 class,編譯器對其產生1個 vtable, 把指向虛函數地址的指針放在該表格中;繼承含有 virtual member function 類的派生類具有以下的特性:
像單繼承1樣,用基類的指針或援用只能訪問基類中定義(或繼承)的成員,不能訪問派生類中引入的成員。當1個類繼承于多個基類的時候,那些基類之間沒有隱含的關系,不允許使用1個基類的指針訪問其他基類的成員。
在多重繼承的 virtual function 機制中,其復雜度圍繞在第2個及后繼的 base class 中,和在履行期間調劑 this 指針;1般規則經過指向第2或后繼 base class 的指針或援用來調用 derived class virtual function。
在虛繼承下,對給定虛基類,不管該類在派生層次中作為虛基類出現多少次,只繼承1個同享的基類子對象。同享的基類子對象稱為虛基類。
class A {
void func();
virtual void x();
};
對非虛函數void func()
,取它的指針得到的是函數的實際地址(即綁定在某個 class object 的地址),如:void (A::*pfunc) () = &A::func;
;
對虛函數virtual void x()
,取它的地址得到的是x
在 class A
的 vtable 中的索引值,如:viod (A::*pfunc) () = &A::x
;
使用 class object 或指向class object 的指針來調用,即用a.*pfunc()
或 pa->*pfunc()
調用;
當我們在 class 中定義 inline function 時,編譯器會根據函數的復雜程度決定是不是真正定義為 inline 類型,對不能真正定義為 inline function 的要求,編譯器可能把它們處理為 static member function;真實的 inline function 的擴大操作是在調用的那1點上,這會帶來參數的求值操作和臨時性對象的管理;