學習C++ -> 類的特殊數據成員


學習C++ -> 類的特殊數據成員





    在構造函數一節的介紹中, 我們已經提到了在C++中有幾類特殊的數據成員不能使用構造函數進行初始化, 他們有自己的初始化方式, 下面就具體介紹下這幾種數據成員。
    
    
一、const 數據成員
    const 類型的數據成員具有只讀屬性, 在構造函數內進行初始化是不允許的, 例如以下代碼:
    

 1     #include <iostream>
 2 
 3     using namespace std;
 4 
 5     class A
 6     {
 7         public:
 8             A(int n = 0) { num = n; }       //在構造函數內使用 n 初始化const型數據成員 num
 9             void showNum() { cout<<"num = "<<num<<endl; }
10         private:
11             const int num;            //const 型數據成員
12     };
13 
14     int main()
15     {
16         A a(10);
17         a.showNum();
18 
19         return 0;
20     }


    嘗試編譯運行時報錯:

        error: uninitialized member 'A::num' with 'const' type 'const int'
        error: assignment of read-only data-member 'A::num'

  
    要初始化 const 型的數據成員, 必須通過初始化表達式來進行初始化, 一經初始化, 其值確定, 不能再被修改, 通過初始化表達式形式如下:

 1     #include <iostream>
 2 
 3     using namespace std;
 4 
 5     class A
 6     {
 7         public:
 8             A(int n = 0):num(n) { }       //使用初始化表達式對const型數據成員進行初始化
 9             void showNum() { cout<<"num = "<<num<<endl; }
10         private:
11             const int num;
12     };
13 
14     int main()
15     {
16         A a(10);
17         a.showNum();
18 
19         return 0;
20     }

 

 



    

二、引用類型的成員
    對於引用類型的成員, 同樣只能通過初始化表達式進行初始化, 錯誤的示例這里不再舉出, 一個通過初始化表對引用類型初始化的示例:
    

 1     #include <iostream>
 2 
 3     using namespace std;
 4 
 5     class A
 6     {
 7         public:
 8             A(int &rn):rNum(rn) { }       //使用初始化表達式對引用型數據成員進行初始化
 9             void showNum() { cout<<"num = "<<rNum<<endl; }
10         private:
11             int &rNum;      //引用類型
12     };
13 
14     int main()
15     {
16         int x = 10, &rx = x;
17         A a(rx);        //傳遞引用類型
18         a.showNum();
19 
20         return 0;
21     }

 

 


    
    
    
三、類對象成員
    類的對象可以作為另一個類的數據成員, 在定義類時, 與普通的數據成員一樣, 在聲明時無法進行初始化, 例如有個Line類中有兩個 Point 類的對象作為數據成員, 在聲明時

    private:
        int xPos(10, 20);
        int yPos(100, 200);


    這樣是錯誤的, 所以在初始化類對象成員時也需要一定的方法。
    
    情況一:
        還以 Line 類和 Point 類為例, 當 Point 類中的數據成員全部為 public 時, 可以在 Line 類的構造函數內完成初始化, 像以下示例的情況:

 1         #include <iostream>
 2 
 3         using namespace std;
 4 
 5         class Point
 6         {
 7             public:
 8                 void printPoint() { cout<<"("<<xPos<<", "<<yPos<<")\n"; }
 9                 int xPos;   //public類型的 xPos 和 yPos
10                 int yPos;
11         };
12 
13         class Line
14         {
15             public:
16                 Line(int x1, int y1, int x2, int y2)
17                 {
18                     M.xPos = x1; M.yPos = y1;       //在構造函數內完成類對象的初始化
19                     N.xPos = x2; N.yPos = y2;
20                 }
21                 void printLine() { M.printPoint(); N.printPoint(); }
22             private:
23                 Point M;        //類對象成員, M和N
24                 Point N;
25         };
26 
27         int main()
28         {
29             Line L(10, 20, 100, 200);
30             L.printLine();
31 
32             return 0;
33         }


        編譯運行的結果:

            (10, 20)
            (100, 200)

            Process returned 0 (0x0)   execution time : 0.500 s
            Press any key to continue.


        代碼說明:
            由於 Point 類中的數據成員全為 public 的, 所以可以通過 對象名.數據成員名 的方式直接進行訪問。 可以看到, Line 類中有兩個 Point 類型的數據成員, M和N, 然后通過 對象名.數據成員名 的方式在 Line 類的構造函數中完成初始化。
            


    情況二:
        由於類的數據成員一般都為 private 型的, 再使用上面的方式進行初始化就不適合了, 因為 private 數據是不允許外部直接訪問的, 將 Point 類中的數據成員改為 private 后再編譯運行代碼便會報出 error: 'int Point::xPos' is private 這樣的錯誤。
    
        要在 Line 類中對 Point 的 private 數據成員進行正常的初始化同樣需要借助初始化表達式來完成, 修改后的示例:

 1         #include <iostream>
 2 
 3         using namespace std;
 4 
 5         class Point
 6         {
 7             public:
 8                 Point(int x, int y) { xPos = x; yPos = y; }
 9                 void printPoint() { cout<<"("<<xPos<<", "<<yPos<<")\n"; }
10             private:
11                 int xPos;   //private類型的 xPos 和 yPos
12                 int yPos;
13         };
14 
15         class Line
16         {
17             public:
18                 Line(int x1, int y1, int x2, int y2):M(10, 20), N(100, 200) { ; }   //借助初始化表達式完成對M,N的初始化
19                 void printLine() { M.printPoint(); N.printPoint(); }
20             private:
21                 Point M;        //類對象成員, M和N
22                 Point N;
23         };
24 
25         int main()
26         {
27             Line L(10, 20, 100, 200);
28             L.printLine();
29 
30             return 0;
31         }

       
        運行輸出后的結果與上例中是相同的。
        
        代碼說明:
            通過初始化表達式對象 L 中的 M、N 數據成員的初始化順序如下: 首先 M 對象的構造函數被調用, 接着調用 N 對象的構造函數, 最后 Line 類的構造函數被調用, 這樣便完成了類對象成員的初始化。
            

 


    
    
四、static類型數據成員
    static 類型的數據成員為靜態成員, 他的特點是: 無論對象創建了多少個, 該數據成員的實例只有一個, 會被該類所創建的所有對象共享, 其中任何一個對象對其操作都會影響到其他對象。該類型的數據初始化是放在類外進行的, 其基本格式如下:
        類型 類名::成員變量名 = 初始化值/表達式;
        
    一個示例: 統計一共創建了多少個對象, 並且在一番銷毀后還剩多少。
    

 1     #include <iostream>
 2 
 3     using namespace std;
 4 
 5     class Book
 6     {
 7         public:
 8             Book() { ibookNumber++; }           //通過構造函數訪問static型數據ibookNumber並使其自增1
 9             ~Book() { ibookNumber--; }          //對象在被撤銷時將static型數據ibookNumber並使其自減1
10             void showNum() { cout<<"Book number = "<<ibookNumber<<endl; }
11         private:
12             static int ibookNumber;             //static類型數據成員 ibookNumber
13     };
14 
15     int Book::ibookNumber = 0;        //在類外對static類型的數據成員進行初始化
16 
17     int main()
18     {
19         Book A; Book B; Book C; Book D; Book E;     //創建一些對象
20         A.showNum();        //使用對象A查看當前對象個數
21         B.showNum();        //使用對象B查看當前對象個數
22         cout<<"銷毀一些對象...\n";
23         B.~Book(); C.~Book();   //將B、C對象進行撤銷
24         D.showNum();            //使用D對象查看剩余對象個數
25         E.showNum();            //使用E對象查看剩余對象個數
26 
27         return 0;
28     }

   
    編譯運行的結果:

        Book number = 5
        Book number = 5
        銷毀一些對象...
        Book number = 3
        Book number = 3

        Process returned 0 (0x0)   execution time : 0.266 s
        Press any key to continue.

       
    代碼說明:
        在上面代碼的類Book中, 我們聲明了一個 static 類型的 ibookNumber 作為創建多少對象的統計變量, Book的構造函數的作用是當對象創建時將 ibookNumber 的值自增1, 而析構函數的則負責將 ibookNumber 自減1。

        main函數中, 創建了 A-E共5個對象, 在創建完成后, 通過 A 對象輸出對象的總數和 B 對象輸出的結果是相同的, 都是5個, 然后銷毀 B、C 對象, 用D、E對象查看剩余對象個數, 結果都為3, 可以看出, static型的數據成員任何對象都可以進行訪問, 並且在創建后所產生的實例是唯一的。

 

 

 

--------------------

 

wid, 2013.02.23

 

上一篇: 學習C++ -> 復制構造函數

 


免責聲明!

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



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