C++——構造函數 constructor

What is constructorhtml

  • C++中,若是你想要建立一個object,有一個函數會自動被調用(不須要programmer顯式調用 ),這個函數就是constructor;
  • constructor的寫法很獨特,其function name必須和class name相同;
  • constructor經過arguments上的差別進而造成ctor的overloading,固然和normal function同樣,ctor也能夠有default arguments;
  • ctor沒有返回值類型;
  • ctor還有個特點功能(ctor獨享),initialization list(初始化列表)。與在{ ... }內部賦值private data,initialization list速度會更快。簡單講,一個variable數值的設定有2個階段,分別是initialization和assignment,initialization先於assignment階段進行。initialization list就是發生在initialization階段,{ ... }內部賦值private data屬於assignment階段。若是不使用initialization list代表你主動放棄initialization階段工做,雖然最後你仍是把數值放入到variable,可是時間晚了些,效率差了些;

默認實參,構造函數,普通函數都有這種性質。ios

ctor's overloadingide

參考:C++——overloading principle analysis函數

關於header file、static、inline、variable hides的一點感想post

咱們知道C不容許overloading,C++容許overloading。C++在編譯器一側時別到的函數名與咱們看到的函數名是有很大差別的。normal function和ctor的overloading方式差很少。下圖事normal function的重載。this

 

注意:黃色部分①②兩個ctor則不能夠同時存在,①對於的ctor全部形參都有默認參數,這時候就至關於default ctor,和②是同樣的效果。編譯器在這種狀況下沒法作出選擇。雖然這也是overloading,可是這種overloading讓compiler困惑url

常量成員函數spa

在函數後頭加const,表示函數不會改變調用者的內容,或 形參在函數內部不會改變。3d

若是忘記加const,右下角的例子,c1是個常量,而real和imag卻有可能改變c1,產生矛盾,編譯器報錯。調試

singleton——把構造函數放在private區

design patrern中 的一種模式

構造函數的做用

①構造對象:在用類定義一個對象時會自動調用構造函數

②初始化對象:類的數據成員每每放在構造函數裏面初始化

③類型轉換:看講解

不管C 、C++都是強類型語言,不一樣類型變量之間不能隨便賦值。不少時候咱們認爲理所固然的賦值都是藉助臨時變量來實現的。看代碼

 1 #include<iostream>
 2 class Test {
 3 public:
 4     Test(int a=0)
 5     {
 6         std::cout << "Create Test Object:" << this<<std::endl;
 7         this->a = a;
 8     }
 9     ~Test()
10     {
11         std::cout << "Free Test Object:" << this << std::endl;
12     }
13 private:
14     int a;
15 };
16 
17 int main(int argc, char **argv)
18 {
19     Test t1;
20     t1 = 100;
21     getchar();
22     return 0;
23 }
View Code

調試結果

 這裏調用了2此構造函數,2次析構函數(析構順序是棧操做順序)。輸出結果解析

第1行輸出:執行第19行,調用構造函數

第2行輸出:執行第20行,調用構造函數。這裏建立了一個臨時Test類型對象(C++爲了凸顯逼格把類類型的變量稱爲對象),100就是傳入構造函數的參數。

第3行輸出:第2行構造完臨時對象後,賦值給了對象t1。賦值之後臨時對象的生命期就結束了,這裏調用析構函數,終結這個臨時對象

第4行輸出:第22行return 0返回後調用析構函數,終結對象t1

畫圖解釋這一過程

這裏面最關鍵的一個環節就是int類型到Test臨時對象轉換,int類型要找到一個途徑來轉換成Test類型。這個途徑是什麼呢?  構造函數

而咱們代碼裏面偏偏有這麼個構造函數,他的參數就是一個整形。若是咱們幹掉這個構造函數,換一個不帶參數的構造函數(或者乾脆不寫構造函數,使用默認的),則不能將100賦值給t1

代碼以下

 1 #include<iostream>
 2 class Test {
 3 public:
 4     Test()
 5     {
 6         std::cout << "Create Test Object:" << this << std::endl;
 7         this->a = a;
 8     }
 9     ~Test()
10     {
11         std::cout << "Free Test Object:" << this << std::endl;
12     }
13 private:
14     int a;
15 };
16 
17 int main(int argc, char **argv)
18 {
19     Test t1;
20     t1 = 100;
21     getchar();
22     return 0;
23 }
View Code
 1 #include<iostream>
 2 class Test {
 3 public:
 4     ~Test()
 5     {
 6         std::cout << "Free Test Object:" << this << std::endl;
 7     }
 8 private:
 9     int a;
10 };
11 
12 int main(int argc, char **argv)
13 {
14     Test t1;
15     t1 = 100;
16     getchar();
17     return 0;
18 }
View Code

這種狀況直接編譯不過。錯誤 C2679 二進制「 = 」: 沒有找到接受「int」類型的右操做數的運算符(或沒有可接受的轉換)。在類型轉換的時候,編譯器試圖尋找能實現轉換的構造函數,能找到就執行構造函數生成一個臨時對象好用於賦值。找不到就報錯。

額外補充:對於隱式類型轉換,生成的臨時對象具備const性質。參考 C++——引用

 explicit關鍵字

有的時候咱們會發現構造函數前面加了個關鍵字explicit,代碼以下

 1 #include<iostream>
 2 class Test {
 3 public:
 4     explicit Test(int a = 0)
 5     {
 6         std::cout << "Create Test Object:" << this << std::endl;
 7         this->a = a;
 8     }
 9     ~Test()
10     {
11         std::cout << "Free Test Object:" << this << std::endl;
12     }
13 private:
14     int a;
15 };
16 
17 int main(int argc, char **argv)
18 {
19     Test t1;
20     t1 = (Test)100;
21     getchar();
22     return 0;
23 }
View Code

在進行賦值 或 類型轉換的時候,若是要藉助構造函數是不容許隱式轉換的。因此第20行必須強制轉換(顯式轉換)。

相關文章
相關標籤/搜索