1. 程式人生 > >C++構造函數(一)

C++構造函數(一)

復習 打開 con div 空間 成對 全局 ptr 分配

本篇是介紹C++的構造函數的第一篇(共二篇),屬於讀書筆記,對C++進行一個系統的復習。

構造函數的概念和作用

全局變量未初始化時為0,局部變量未初始化時的值卻是無法預測的。這是因為,全局變量的初始化是再程序裝載時便一次性完成的,自動地初始化為零並不會有額外的開銷,因此編譯器默認初始化為零。但是對局部變量並沒有這樣的操作,需要程序去完成初始化。

基本類型變量的初始化只需要在定義時賦值就可以了,但是對於對象的初始化,情況就要復雜一些。比如,有的對象需要在創建時就令某個指針指向一塊內存空間,這就涉及到空間的分配;再比如,有的對象包含文件操作,在創建時就需要打開特定文件。舉這兩個例子是要說明,對象的初始化,不僅僅是簡單賦值那麽簡單。因此構造函數(constructor)是必要的,它的存在就是為了完成對象的初始化工作。

構造函數名字和類名一樣,沒有返回值,可以重載。可以有多個構造函數,如果沒有就自動生成一個默認的構造函數,但是它什麽也不做。

默認構造函數

自動生成的構造函數是一個沒有參數的構造函數。但凡自己已經寫了一個構造函數,都不會自動生成無參的構造函數。不論是程序員自己寫的無參構造函數還是自動生成的無參構造函數,只要是無參構造函數,就稱為默認構造函數。那麽,考慮下面一種情況:程序員只寫了有參的構造函數,這種情況下就不存在默認構造函數。所以默認構造函數不一定存在,或者說無參的構造函數不一定存在。為什麽要強調無參的構造函數不一定存在,有沒有哪種構造函數一定是存在的呢?復制構造函數是一定存在的,在後文介紹。

對象在生成的時候一定會調用某個構造函數初始化,而對象一旦生成,就再也不會在其上調用構造函數。

構造函數是負責內存的分配嗎?不是的,它只負責初始化。所以創建一個對象的過程是,先內存分配(在堆或棧上),之後在分配好的內存上調用構造函數。

構造函數在數組中的使用

int a[3] = { 0 ,1 ,2 }; 這樣的語句就實現了數組的初始化。如何給一個對象數組初始化呢,可以使用類似的方法。

1 class CNum {
2 
3 int num;
4 public:
5 
6 CNum(){ num = 0;}
7 CNum(int a){ num = a;}
8 CNum(int a, int b){ num = a + b;}
9 }

可以這樣調用:

1 CNum n1[3];                   //
調用了三次無參構造函數,結果是{0,0,0} 2 CNum n2[3] = {0, 1, 2};           //調用了三次CNum(int a),結果是{0,1,2} 3 CNum n3[3] = {0, 1};             //調用了兩次CNum(int a),和一次無參構造函數,結果是{0,1,0} 4 CNum n4[3] = {0, CNum(1,2), CNum(2,3)};  //調用了一次無參構造函數和兩次CNum(int a, int b),結果是{0,3,5}

想在堆上生成數組可以這樣:

1 CNum * ptrnum[3] = {new CNum(1,2), new CNum(2,3)};

這樣生成的實際上是一個指針數組,前兩個元素指向的對象使用了CNum(int a, int b)初始化,第三個元素沒有初始化,是一個野指針(請避免這樣做)。所以這一個語句實際上調用了兩次構造函數。

C++構造函數(一)