成員函式的一種,名字與類名相同,可以有引數,不能有返回值(void也不行)。
乙個類可以有多個建構函式。
如果定義類時沒寫建構函式,則編譯器生成乙個預設的無參建構函式,這個建構函式不做任何操作。如果定義了建構函式,則編譯器不生成預設的無參建構函式。
物件生成時建構函式自動被呼叫,物件一旦生成,就再也不能在其上執行建構函式。物件占用的儲存空間不是建構函式分配的,建構函式是在物件已經占用的儲存空間上做一些初始化操作。只要物件生成,建構函式就會自動呼叫,不管這個物件是如何生成的。
例如:
class
complex;
complex::complex(double r,double i)
complex c1;//error,缺少建構函式的引數
complex *pc=new complex;//error,沒有引數
complex c1(2);
complex c1(2,4),c2(3,5);
complex *pc=new complex(3,4);
建構函式最好是public的,private建構函式不能直接用來初始化物件。例如,
class csample
};int main()
建構函式在陣列中的使用:
class csample;//陣列的兩個元素都呼叫有參建構函式
cout
<<"step2"
<2]=;//第乙個元素呼叫2建構函式,第二個呼叫1建構函式
cout
<<"step3"
delete array4;
return0;}
函式的輸出為:
constructor 1 called
constructor 1 called
step1
constructor 2 called
constructor 2 called
step2
constructor 2 called
constructor 1 called
step3
constructor 1 called
constructor 1 called
class
test //(1)
test
(int
n,int
m){}//(2)
test
(){} //(3)
};test array1[3]=;
//陣列有三個元素但是只給出了兩個初始值,因此三個元素分別用(1)
(2)(3)初始化
test array2[3]=;
//三個元素分別用(2)
(2)(1)初始化
test *parray[3]=;
//parray是指標陣列,不是物件陣列,它的三個元素都是指標分別指向某塊區域。如果只寫test *parray[3]而不寫等號後面的部分,則沒有物件生成,也不會引發test建構函式的呼叫。這裡只初始化了陣列的前兩個元素,因此只有兩個物件生成,new test
(4)的返回型別是test*,賦值給陣列的第乙個元素,也就是把新構造的物件的位址賦值給指標陣列的第乙個元素。這裡兩個元素分別呼叫(1)
(2)初始化。
只有乙個引數,即同類物件的引用,形如x::x(x&)或x::x(const x &),只能是物件的引用,不能是物件,不允許有形如x::x(x)的複製建構函式。
如果沒有定義複製建構函式,那麼編譯器生成預設複製建構函式,預設的複製建構函式完成複製功能。如果自己定義了複製建構函式,則預設的複製建構函式不存在。
複製建構函式起作用的三種情況:
1)當用乙個物件去初始化同類的另乙個物件時
complex c2(c1);
complex c2 = c1;//初始化語句,非賦值語句,呼叫複製建構函式
complex c1,c2;
c2 =c1;//賦值語句,不會呼叫複製建構函式,複製建構函式只有在初始化時才會呼叫
2)如果某函式的乙個引數是類a的物件,那麼該函式被呼叫時,類a的複製建構函式將被呼叫來初始化形參
class a;
a(a &a);
void func(a a1){}
int main()
程式輸出結果:copy
constructor
called
3)如果函式的返回值是類a的物件時,則函式返回時,a的複製建構函式被呼叫
class a
a(const a &a);
a func()
//返回值物件被初始化時呼叫複製建構函式,其引數是b,這裡返回值物件a的值是否等於b取決於複製建構函式怎麼寫
int main()
complex(double r,double i)
};int main()
輸出:intconstructor called
intconstructor called
9,0
名字與類名相同,在前面加『~』,沒有引數和返回值,乙個類最多只有乙個析構函式。
物件消亡時,析構函式自動被呼叫。
定義類時沒寫析構函式,則編譯器生成預設析構函式;定義了析構函式,則編譯器不生成預設析構函式。
析構函式不涉及釋放使用者申請的記憶體釋放等工作,如果使用者自己申請了記憶體空間,那麼使用者必須自己釋放,不然程式不會自動釋放使用者自己申請的記憶體空間。也就是說,程式裡面寫了new就必須有對應的delete,否則程式結束時不會自動析構使用者new的這塊空間。
析構函式和陣列:物件陣列生命期結束時,物件陣列的每個元素的析構函式都會被呼叫。
析構函式和運算子delete:delete運算導致析構函式呼叫。
ctest *ptest;
ptest = new ctest[3];//構造函式呼叫3次
delete ptest;//析構函式呼叫3次
class demo
func();
cout
<<"main ends"
0;}
輸出:
id=1 constructed
id=4 constructed
id=6 constructed
id=6 destructed
main
id=5 constructed
id=5 destructed
id=2 constructed
id=3 constructed
func
id=3 destructed
main ends
id=6 destructed
id=2 destructed
id=1 destructed
注: 1.d4=6是型別轉換,會生成臨時物件,因此有對臨時物件生成的建構函式和析構函式的呼叫。
2. 離物件最近的花括號是物件的作用域,作用域標誌著物件的生命週期,在物件的生命週期結束時要被析構。
3.func()函式內部定義了靜態變數d2和普通變數d3,它們的作用域是這個函式內部,但是靜態變數是在整個程式結束時析構,因此當func()結束時只析構變數d3。
4.d4是在main函式內部的區域性變數,所以main函式結束時d4析構,d1是全域性變數要在整個程式結束時析構,d2是靜態變數也要在整個程式結束時析構,先建立的後析構。
C 複製建構函式與型別轉換建構函式
複製構造引數只有乙個引數,即對同類物件的引用,形如 x x x 或x x const x 常用後者。若使用者未定義,則編輯器會生成預設的複製建構函式,完成複製的功能。class complex complex c1 呼叫預設無參建構函式 complex c2 c1 呼叫預設的複製建構函式,將 c2 ...
C 建構函式 析構函式 複製建構函式
無聊的廢話 距離開始放假已經過去半個月了,這半個月,品讀了一本實用型的繪畫書籍,作了幾幅作品,又做了乙個模型,只是探索未知領域總會遇到各種問題,甚至難以解決的問題,筆者頹廢了兩天煲了一部劇,覺得自己深深的辜負了時間,決定動手總結一下學過的知識,主要是總結資料結構,不過筆者看到當初c 的筆記,決定再鞏...
建構函式,複製建構函式和析構函式
這些函式在網上很容易就可以查到定義和寫法,這裡就不贅述了。令人感興趣的是這些函式什麼時候執行,特別是複製建構函式和析構函式。用編寫的一段 很醜的 來說明。include include include class point point const point obj point double ge...