C++中構造函數的手動和自動調用方式


1,對象的構造通過構造函數來完成,和類名相同且沒有返回值,這個時候只有參   數一個特性,構造函數可以自定義參數,這個參數一般而言就是對類進行初始  化來使用的;帶有參數的構造函數的意義在於可以使得每個對象有不同的初始   化狀態(生活中每個事物必然包含自己的初始化狀態,不如人的出生,面向對   象用來將生活中的事物映射的程序設計領域,所以現實世界的情況都必須可以  用面向對象的語言來描述,因此帶有參數的構造函數就是非常必要的);

 

 2,帶有參數的構造函數:

    1,構造函數可以根據需要定義參數;

    2,一個類中可以存在多個重載的構造函數;

    3,構造函數的重載遵循 C++ 重載的規則;

    4,代碼示例:

1 class Test
2 {
3 public:
4     Test(int v)
5     {
6         // use v to initialize member
7     }
8 };

   

 3,對象定義和對象聲明的區別:

    1,對象定義:申請對象的空間並調用構造函數;

       1,第一步,必須申請對象所占用的內存空間;

       2,第二步,調用構造函數;

    2,對象聲明:告訴編譯器存在這樣一個對象;

       1,對象在哪里定義的不知道,鏈接的時候回去找;

       2,預處理,編譯器對源代碼進行檢查並生成目標文件,鏈接器在各個目標文件中尋找目標文件存在的一些名字;

       3,對象聲明時,沒有對象定義時的兩個步驟;

    3,代碼示例:

1 Test t;  // 定義對象並調用構造函數;
2 
3 Int main()
4 {
5     // 告訴編譯器存在名為 t 的Test對象;
6     extern Test t;
7 
8     return 0;
9 }

    4,對象的聲明中可以在構造函數參數中給出默認值,對象的定義中不能夠在構 造函數參數中給出默認值;

   

 4,構造函數的自動調用(第一種初始化對象方式):

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 public:
 6     Test() 
 7     { 
 8         printf("Test()\n");
 9     }
10     
11     Test(int v) 
12     { 
13         printf("Test(int v), v = %d\n", v);
14     }
15 };
16 
17 int main()
18 {
19     Test t;      // 調用 Test()
20     Test t1(1);  // 初始胡第一種方式的參數式自動調用,調用 Test(int v);這里也是定義對象,看上去非常像函數調用,但是這里是告訴編譯器要調用帶有參數的函數,由重載規則確定調用的是那個構造函數;
21     Test t2 = 2; // 初始化第一種方式的賦值式自動調用,調用 Test(int v);C 語言中初始化的方法,定義一個變量后,立即指明一個值,通過賦值符號指明;這在面向對象中其實也是對象的定義,並且指明想用右值初始化左值;
22  
23     t = t2;  // 這是賦值操作,這里運行后不會調用構造函數,沒有打印語句;初始化會調用構造函數,賦值則看后續課程;
24  
25     int i = 1;  // 用 1 對 i 進行初始化;
26     i = 1;  // 用 1 對 i 進行賦值;賦值和初始化是不同的;在面向對象當中,不同在於初始化是要調用構造函數的;
27        
28     int i(100);  // 初始化的第二種寫法,同 int i = 100;; 
29     
30     printf("i = %d\n", i);
31     
32     return 0;
33 }

    1,實驗結果說明:

       1,初始化和賦值看上去相同之處在於當初始化用賦值符號表達的時候;

       2,不同之處在於初始化要調用構造函數,而賦值不會;

   

 5,構造函數的調用:

    1,一般情況下,構造函數在對象定義時被自動調用;

    2,一些特殊情況下,需要手工調用構造函數:

       1,如何創建對象數組;

   

 6,構造函數的手工調用(第二種初始化對象方式)編程實驗:

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int m_value;
 7 public:
 8     Test() 
 9     { 
10         printf("Test()\n");
11         
12         m_value = 0;
13     }
14     Test(int v) 
15     { 
16         printf("Test(int v), v = %d\n", v);
17         
18         m_value = v;
19     }
20     int getValue()
21     {
22         return m_value;
23     }
24 };
25 
26 int main()
27 {
28     Test ta[3];  // 按照 C 語言的方法定義 3 個 Test 對象的數組 ta;結果調用了 3 個 Test() 函數;
29     
30     for(int i=0; i<3; i++)  // 循環結果打印出 3 個 0,這不一定是我們想要的;編譯器默認的調用了 Test();
31     {
32         printf("ta[%d].getValue() = %d\n", i , ta[i].getValue());
33     }
34     
35     Test ta[3] = {Test(), Test(1), Test(2)};  // 手動調用構造函數;
36     
37     for(int i=0; i<3; i++)  // 循環結果為 0 1 2;分別調用了相應的構造函數;
38     {
39         printf("ta[%d].getValue() = %d\n", i , ta[i].getValue());
40     }
41     
42     Test t = Test(100);  // 初始化第二種方式,手工調用構造函數;
43     
44     printf("t.getValue() = %d\n", t.getValue());
45     
46     return 0;
47 }

   

 7,小實例:

    1,需求:開發一個數組類解決原生數組的安全性問題:

       1,提供函數獲取數組長度;

           1,C++ 要兼容 C 語言中的數組,但是 C 語言中的數組沒有長度信息,用着用着就越界了;

       2,提供函數獲取數組元素;

       3,提供函數設置數組元素;

      

 8,數組類的實現編程實驗:

    1,IntArray.h 文件:

 1 #ifndef _INTARRAY_H_
 2 #define _INTARRAY_H_
 3 
 4 class IntArray
 5 {
 6 private:
 7     int m_length;
 8     int* m_pointer;
 9 public:
10     IntArray(int len);
11     int length();
12     bool get(int index, int& value);  // 用 bool 類型作為返回值是為了安全性,安全性的體現見數組類的實現;
13     bool set(int index ,int value);
14     void free();  // 用來釋放 m_pointer 指向的堆空間
15 };
16 
17 #endif

    2,IntArray.cpp 文件:

 1 #include "IntArray.h"
 2 
 3 IntArray::IntArray(int len)  // 不加作用域分辨符時,是全局函數(此時僅名字前綴相同而已),所以要加作用域分辨符指明是數組類中的函數;
 4 {
 5     m_pointer = new int[len];  // new int(len) 指的是設置初始值;
 6     
 7     for(int i=0; i<len; i++)
 8     {
 9         m_pointer[i] = 0;
10     }
11     
12     m_length = len;
13 }
14 
15 int IntArray::length()
16 {
17     return m_length;
18 }
19 
20 bool IntArray::get(int index, int& value)
21 {
22     bool ret = (0 <= index) && (index < length());  // 進行安全性檢查,是安全性的體現;
23     
24     if( ret )
25     {
26         value = m_pointer[index];  // 通過引用返回一個值;
27     }
28     
29     return ret;  // 越界則返回 false;
30 }
31 
32 bool IntArray::set(int index, int value)
33 {
34     bool ret = (0 <= index) && (index < length());
35     
36     if( ret )
37     {
38         m_pointer[index] = value;
39     }
40     
41     return ret;
42 }
43 
44 void IntArray::free()
45 {
46     delete[]m_pointer;
47 }

    3,IntArray 的使用:

 1 #include <stdio.h>
 2 #include "IntArray.h"
 3 
 4 int main()
 5 {
 6     IntArray a(5);    
 7     
 8     for(int i=0; i<a.length(); i++)
 9     {
10         a.set(i, i + 1);
11     }
12     
13     for(int i=0; i<a.length(); i++)
14     {
15         int value = 0;
16         
17         if( a.get(i, value) )
18         {
19             printf("a[%d] = %d\n", i, value);
20         }
21     }
22     
23     a.free();
24     
25     return 0;
26 }

    4,這里展示了面向對象的強大,我們可以通過類來封裝一些之前學習到的概念,並且可以將這些概念上的缺陷通過封裝來彌補開來;

   

 9,小結:

    1,構造函數可以根據需要定義參數;

    2,構造函數之間可以存在重載關系;

    3,構造函數遵循 C++ 中重載函數的規則;

    4,對象定義時會觸發構造函數的調用;

       1,構造函數調用方式分為自動調用和手工調用兩種;

       2,自動調用的形式又分為參數式和賦值式;

       3,即初始化時,分為兩種調用方式三種書寫形式;

    5,在一些情況下可以手動調用構造函數;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM