C++類的初始化

來源:互聯網
上載者:User

轉載自:http://blog.csdn.net/coder_xia/article/details/7447822

1、關於建構函式

1)用建構函式確保初始化

對於一個空類

[cpp] view plaincopy

  1. class Empty { };  

編譯器會自動聲明4個預設函數:建構函式,拷貝建構函式,賦值函數,解構函式(當然,如果不想使用自動產生的函數,就應該明確拒絕),這些產生的函數都是public且inline。建構函式對資料成員進行初始化,使用未初始化值可能導致無法預知的錯誤,所以,確保每一個建構函式都將每一個成員初始化。

 

2)為什麼建構函式不能有傳回值

如果有傳回值,要麼編譯器必須知道怎麼處理傳回值,要麼就客戶程式員顯式調用建構函式和解構函式,這樣,還有安全性嗎?

3)為什麼建構函式不能為虛函數

簡單來說,虛函數調用的機制,是知道介面而不知道其準確物件類型的函數,但是建立一個對象,必須知道對象的準確類型;當一個建構函式被調用時,它做的首要事情之一就是初始化它的VPTR來指向VTABLE。

4)建構函式的一個面試題:

 

[cpp] view plaincopy

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Base   
  5. {  
  6. private:  
  7.     int i;  
  8. public:  
  9.     Base(int x)  
  10.     {  
  11.         i = x;  
  12.     }  
  13. };  
  14.   
  15. class Derived : public Base  
  16. {  
  17. private:  
  18.     int i;  
  19. public:  
  20.     Derived(int x, int y)  
  21.     {  
  22.         i = x;  
  23.     }  
  24.     void print()  
  25.     {  
  26.         cout << i + Base::i << endl;  
  27.     }  
  28. };  
  29.   
  30. int main()  
  31. {  
  32.     Derived A(2,3);  
  33.     A.print();  
  34.     return 0;  
  35. }  

首先,是存取權限問題,子類中直接存取Base::i是不允許的,應該將父類的改為protected或者public(最好用protected)

 

其次,統計父類和子類i的和,但是通過子類建構函式沒有對父類變數進行初始化;此處編譯會找不到建構函式,因為子類調用建構函式會先找父類建構函式,但是沒有2個參數的,所以可以在初始化列表中調用父類建構函式

最後個問題,是單參數的建構函式,可能存在隱式轉換的問題,因為單參數建構函式,和拷貝建構函式形式類似,調用時很可能會發生隱式轉換,應加上explicit關鍵字,修改後如下(程式員面試寶典上只改了前2個)

 

[cpp] view plaincopy

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Base   
  5. {  
  6. protected:  
  7.     int i;  
  8. public:  
  9.     explicit Base(int x)  
  10.     {  
  11.         i = x;  
  12.     }  
  13. };  
  14.   
  15. class Derived : public Base  
  16. {  
  17. private:  
  18.     int i;  
  19. public:  
  20.     Derived(int x, int y):Base(x)  
  21.     {  
  22.         i = y;  
  23.     }  
  24.     void print()  
  25.     {  
  26.         cout << i + Base::i << endl;  
  27.     }  
  28. };  
  29.   
  30. int main()  
  31. {  
  32.     Derived A(2,3);  
  33.     A.print();  
  34.     return 0;  
  35. }  

 

2、初始化列表

1)使用初始化列表提高效率

常用的初始化可能如下:

 

[cpp] view plaincopy

  1. class Student   
  2. {  
  3. public:  
  4.     Student(string in_name, int in_age)  
  5.     {  
  6.         name = in_name;  
  7.         age = in_age;  
  8.     }  
  9. private :  
  10.     string name;  
  11.     int    age;  
  12. };  

    以前樓主也習慣這麼寫,可以達到預期效果,不過不是最佳做法,因為在建構函式中,是對name進行賦值,不是初始化,而string對象會先調用它的預設建構函式,再調用string類(貌似是basic_string類)的賦值建構函式;對於上例的age,因為int是內建類型,應該是賦值的時候獲得了初值。

 

    要對成員進行初始化,而不是賦值,可以採用初始化列表(member initialization list)改寫為如下:

 

[cpp] view plaincopy

  1. class Student   
  2. {  
  3. public:  
  4.     Student(string in_name, int in_age):name(in_name),age(in_age) {}  
  5. private :  
  6.     string name;  
  7.     int    age;  
  8. };  

    結果與上例相同,不過在初始化的時候調用的是string的拷貝建構函式,而上例會調用兩次建構函式,從效能上會有不小提升

    有的情況下,是必須使用初始化列表進行初始化的:const對象、引用對象

2)初始化列表初始順序

考慮以下代碼:

 

[cpp] view plaincopy

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Base   
  5. {  
  6. public:  
  7.     Base(int i) : m_j(i), m_i(m_j) {}  
  8.     Base() : m_j(0), m_i(m_j) {}  
  9.     int get_i() const  
  10.     {  
  11.         return m_i;  
  12.     }  
  13.     int get_j() const  
  14.     {  
  15.         return m_j;  
  16.     }  
  17.   
  18. private:  
  19.     int m_i;  
  20.     int m_j;  
  21.   
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     Base obj(98);  
  27.     cout << obj.get_i() << endl << obj.get_j() << endl;  
  28.     return 0;  
  29. }  

     
輸出為一個隨機數和98,為什麼呢?因為對於初始化列表而言,對成員變數的初始化,是嚴格按照聲明次序,而不是在初始化列表中的順序進行初始化,如果改為賦值初始化則不會出現這個問題,當然,為了使用初始化列表,還是嚴格注意聲明順序吧,比如先聲明數組大小,再聲明數組這樣。

 

1)使用類的初始化可以提高效率:

 1 #include<iostream> 2 #include<stdio.h> 3 using namespace std; 4 class boy { 5       public: 6   boy(string name,int age):name(name),age(age)//類的初始化 7       { 8       cout<<this->name<<endl; 9       cout<<this->age<<endl;10       }11       ~boy()12       {13           cout<<this->name<<endl<<this->age<<endl;14       }15       string name;16       int age;17 };18 class desk{19 20 public:21       desk(int x):w(x),h(w){}22       int h;23       int w;24 };25 int main()26 {27     boy a("abc",22);28     desk b(25);29 cout<<b.h<<endl<<b.w<<endl;//類的初始化順序按照聲明的順序30     return 0;31 32   }

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.