1. 程式人生 > >詳談c++的構造和析構

詳談c++的構造和析構

clu iostream 告訴 src int 分配 pub none 空間

c++的構造

  概念:對象被創建時,編譯系統對象分配內存空間,並自動調用該構造函數->由構造函數完成成員的初始化工作

  例:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A():a(1),b(0){cout<<"A"<<endl;}
 7 private:
 8     int a;
 9     const int  b;
10 };
11 
12 int main()
13 {
14     A a;
15     A*b(&a);
16 A &c(a); 17 return 0; 18 }

  A *(&a) 和 A &c(a)都沒有產生新的對象,所以都沒有在調用構造函數,輸出結果為:A

  可通過構造函數對成員變量進行初始化

子父類的構造與析構

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A(){cout<<"A"<<endl;}
 7     virtual ~A(){cout << "~A" <<endl;}
8 }; 9 10 class B{ 11 public: 12 B(){cout << "B" <<endl;} 13 virtual ~B(){cout << "~B" << endl;} 14 }; 15 16 class C : public A{ 17 public: 18 C(){cout << "C" << endl;} 19 virtual ~C(){cout << "~C" <<endl;} 20 private: 21 B b; 22 };
23 24 int main() 25 { 26 C c; 27 return 0; 28 }

輸出結果為:

1 A
2 B
3 C
4 ~C
5 ~B
6 ~A

  父類的構造函數:

  (1)如果某個類具有基類,執行基類的默認構造函數。除非在ctor-initializer中調用了基類構造函數,此時調用這個構造函數,而不是默認構造函數

  (2)類的非靜態數據成員按照聲明的順序創建

  (3)執行該類的構造函數

  父類的析勾函數:

  (1)調用類的析構函數

  (2)銷毀類的數據成員,與創建順序相反

  (3)如果有父類,調用父類的析構函數

  註意所有的析構函數都是virtual。如果前面的析構函數沒有聲明為virtual,代碼也可以繼續運行。然而,如果代碼使用delete刪除一個實際指向派生類的基類指針,析構函數調用鏈將被破壞。如下:

  

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A(){cout<<"A"<<endl;}
 7     ~A(){cout << "~A" <<endl;}
 8 };
 9 
10 
11 class C : public A{
12 public:
13     C(){cout << "C" << endl;}
14     ~C(){cout << "~C" <<endl;}
15 };
16 
17 int main()
18 {
19     A *c = new C();z
20     delete c;
21     return 0;
22 }

輸出結構為:

A
C
~A

註:當基類代碼中顯示了沒有默認構造函數,相關版本的派生類必須顯示地告訴編譯器如何調用Super的構造函數,否則代碼將無法編譯。

技術分享
 1 class Super
 2 {
 3 public:
 4    Super(int i);            
 5 };
 6 class Sub : public Super
 7 {
 8 public:
 9     Sub(int i);    
10 };
11 
12 Sub::Sub(int i) : Super(i)
13 {
14 
15 }
View Code

  從派生類向基類傳遞構造函數的參數很正常,毫無問題,但是無法傳遞數據成員。因為在調用基類的構造之後才會初始化數據成員。如果將數據成員作為參數傳遞給父類構造函數,數據成員不會初始化。

  

  父類的析構函數

  析構函數的調用順序剛好與構造函數相反:

  (1)調用類的析構函數

  (2)銷毀類的數據成員,與創建的順序相反

  (3)如果有父類,調用父類的析構函數

  註意:所有的析構函數都是virtual。根據經驗,所有析構函數都應該聲明為virtual。如果前面的析構函數沒有聲明為virtual,代碼也可以繼續運行。然而,如果代碼使用delete刪除一個實際指向派生類的基類指針,析構函數調用鏈將被破壞。

  從技術角度看,將基類的析構函數聲明為virtual,可以糾正上面的問題。派生類將自動“虛化”。然而,建議顯示地將所有析構函數聲明為virtual

  

詳談c++的構造和析構