歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++構造函數和拷貝構造函數詳解

構造函數、析構函數與賦值函數是每個類最基本的函數。它們太普通以致讓人容易麻痺大意,其實這些貌似簡單的函數就象沒有頂蓋的下水道那樣危險。

每個類只有一個析構函數和一個賦值函數,但可以有多個構造函數(包含一個拷貝構造函數,其它的稱為普通構造函數)。

對於任意一個類A,如果不想編寫上述函數,C++編譯器將自動為A 產生四個缺省的函數,例如:

A(void); // 缺省的無參數構造函數

A(const A &a); // 缺省的拷貝構造函數

~A(void); // 缺省的析構函數

A & operate =(const A &a); // 缺省的賦值函數

這不禁讓人疑惑,既然能自動生成函數,為什麼還要程序員編寫?原因如下:

<1>如果使用“缺省的無參數構造函數”和“缺省的析構函數”,等於放棄了自主“初始化”和“清除”的機會,C++發明人Stroustrup 的好心好意白費了。

<2>“缺省的拷貝構造函數”和“缺省的賦值函數”均采用“位拷貝”而非“值拷貝”的方式來實現,倘若類中含有指針變量,這兩個函數注定將出錯。

C++ 默認構造函數 :

1、每個類必須有一個構造函數,否則沒法創建對象;

2、若 程序員沒有提供任何構造函數,則 C++提供一個默認的構造函數,該默認構造函數是無參構造函數,它僅負責創建對象,不做任何初始化的工作;

3、只要 programer 定義了一個構造函數(不管是無參還是有參構造),C++就不再提供默認的默認構造函數。即如果為類定義了一個帶參的構造函數,還想要無參構造函數,就必須自己定義;

4、與變量定義類似,在用默認構造函數創建對象時,如果創建的是全局對象或靜態對象,則對象的位模式全為 0,否則,對象值是隨機的。

C++默認拷貝構造函數:

1、默認的拷貝構造函數執行的順序與其他用戶定義的構造函數相同,執行先父類後子類的構造.

2、拷貝構造函數對類中每一個數據成員執行成員拷貝(memberwise Copy)的動作.

3、如果數據成員為某一個類的實例,那麼調用此類的拷貝構造函數.

4、如果數據成員是一個數組,對數組的每一個執行按位拷貝.

5、如果數據成員是一個數量,如int,double,那麼調用系統內建的賦值運算符對其進行賦值.

請看下面代碼:

  1. #include <iostream>   
  2. #include <string>   
  3. using namespace std;  
  4.   
  5. class Student  
  6. {  
  7. public:  
  8.     Student()  
  9.     {  
  10.         cout << "構造函數1" << endl;  
  11.     }  
  12.     Student(int k)  
  13.     {  
  14.         cout << "構造函數2" << endl;  
  15.         i = k;  
  16.     }  
  17.     Student(Student const &m)  
  18.     {  
  19.         cout << "拷貝構造函數" << endl;  
  20.         i = m.i * (-1);  
  21.     }  
  22.   
  23.     void p()  
  24.     {  
  25.         cout << i << endl;  
  26.     }  
  27.     ~Student()  
  28.     {  
  29.         cout << "析構函數" << endl;  
  30.     }  
  31. protected:  
  32.     int i;  
  33. };  
  34.   
  35. int main(int argc, char **argv)  
  36. {  
  37.     Student s(9818);  
  38.     // 調用構造函數2   
  39.     s.p();  
  40.   
  41.     Student t(s);  
  42.     // 調用拷貝構造函數   
  43.     t.p();  
  44.   
  45.     Student k = s;  
  46.     // 調用拷貝構造函數   
  47.     k.p();  
  48.   
  49.     Student *p = new Student(s);  
  50.     // 調用拷貝構造函數   
  51.     p->p();  
  52.   
  53.     Student m;  
  54.     // 調用構造函數1   
  55.     m = s;// 賦值運算   
  56.     m.p();  
  57.   
  58.     return 0;  
  59. }  

運行結果:

  1. 構造函數2  
  2. 9818  
  3. 拷貝構造函數  
  4. -9818  
  5. 拷貝構造函數  
  6. -9818  
  7. 拷貝構造函數  
  8. -9818  
  9. 構造函數1  
  10. 9818  
  11. 析構函數  
  12. 析構函數  
  13. 析構函數  
  14. 析構函數  
Copyright © Linux教程網 All Rights Reserved