前一篇文章中說到,內聯成員函數的定義有兩種方式,一種是在類體內部直接定義,第二種是在類體外定義。下面是代碼:
第一種定義方式:
class Test { public: void add(int a, int b) //類體中直接定義時為內聯函數。 { return a+b; } };第二種定義方式為:
inline Test::add(int a, int b) //在類體外定義 { return a+b; }內聯函數的目的主要是為了提高程序執行的效率,編譯器在編譯的時候會將代碼直接嵌入到調用的地方,從而減少了函數調用的開銷,如果不用內聯函數,直接嵌入代碼,則代碼體積將增大,這實際上是以空間換取時間的策略。所以內聯函數的代碼必須短小,內聯函數對編譯器而言僅僅是一個提示,另外,如果函數中含有switch for 等語句,則編譯器不會將其解讀為內聯。
下面講講成員函數的重載
成員函數的重載是有條件的,首先必須具有相同的作用域,且參數不同(可以是參數類型不同,參數個數不同,參數順序不同),函數名相同。這樣的成員函數才構成重載。下面是重載的例子:
class Test { public: void Init(); void Init(int x); void Init(int x, int y); void Init(int x, int y, int z); //void Init(int x=0, int y= 0, int z= 0 ); //與void Init();函數產生了二義性,編譯器無法區分 };在上面這個例子中,定義了多個Init函數,由於他們的參數不同,所以構成重載,但是成員函數的重載需要注意的是,對於帶有缺省值參數的成員函數的重載需要避免二義性,如上述代碼中的注釋行。它與不帶參數的成員函數Init()就產生了二義性,編譯器對此無法區分,因此會報錯。
類與結構體(struct 與 class)
在C中的結構體struct其實與C++中的class有點類似的,它們都可以將各種數據結構與方法封閉在一個容器中。唯一的區別在於:在未指定訪問權限時,struct默認是public的,而class默認是private的。如下:
class Test { int x; //actually x is private. };
struct Test { int x; //x is public };在class中可以定義函數,其實在C++中的struct內也可以定義函數,只不過他們的訪問權限均為public的,如果class內定義的所有數據成員與成員函數均為public,則與struct定義沒有任何區別。下面這段代碼非常簡單,可以看出二者的區別。
struct Test2 { int x_; int y_; int z_; void Init(int x, int y, int z) { x_ = x; y_ = y; z_ = z; } }; class Test3 { int x_; int y_; int z_; void Init(int x, int y, int z ) { x_ = x; y_ = y; z_ = z; } }; int main() { Test2 t; //在C++中,struct也是一個類,不需要加上struct t.Init(10,20,30); Test2 t2 = {10,20,30}; //C中結構體的初始化,這是允許的 Test3 t3; t3.Init(10,20,30);//Error,Init在t3中是private的,外部無法直接訪問 Test3 t4 = {10,20,30}; //Error,在class中,數據成員為private,不能像struct那樣初始化。 }
關於this指針
為了搞清this指針,需要了解一個背景:在C++中,成員函數的代碼對所有對象而言是共享的,而每個對象的數據成員空間各自獨立,那麼當每個對象都調用成員函數時,成員函數如何區別它應該操作哪一個對象的數據呢?換句話說,成員函數怎麼知道它要操作的是調用它的對象的數據成員?這主要是C++編譯器來完成,C++編譯器在每次成員函數調用時,在第一個參數會增加一個對象的指針,以告訴成員函數它要操作的是哪個對象的數據。編譯器傳遞的這個指針是不可見的,是隱含的。
我們程序代碼中調用成員函數是這樣的:
Test t1; t1.Init(10,20,30);
Test t1; t1.Init(&t1, 10, 20, 30);這個被編譯器傳遞進去的指針就是this指針了,這樣在成員函數代碼被執行時就指向了t1的數據成員。當然,我們在成員函數定義時可以將這個this指針省略。