C++構造函數(shù)
當創(chuàng)建一個對象時,往往需要做一些初始化工作,例如對數(shù)據(jù)成員賦值等。為了解決這個問題,C++提供了構造函數(shù)。
構造函數(shù)(Constructor)是一種特殊的成員函數(shù),它的名字和類名相同,沒有返回值,不需要用戶調用(用戶也不能調用),而是在創(chuàng)建對象時自動執(zhí)行。構造函數(shù)的作用是在創(chuàng)建對象時進行初始化工作,最常見的就是對成員變量賦值。
一個構造函數(shù)的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#include <iostream> using namespace std; class Student{ private : char *name; int age; float score; public : //聲明構造函數(shù) Student( char *, int , float ); //聲明普通成員函數(shù) void say(); }; //定義構造函數(shù) Student::Student( char *name1, int age1, float score1){ name = name1; age = age1; score = score1; } //定義普通成員函數(shù) void Student::say(){ cout<<name<< "的年齡是 " <<age<< ",成績是 " <<score<<endl; } int main(){ //根據(jù)構造函數(shù)創(chuàng)建對象 Student stu( "小明" , 15, 90.5f); //傳參形式類似于函數(shù)調用 stu.say(); return 0; } |
運行結果:
1
|
小明的年齡是 15,成績是 90.5 |
在類中我們定義了一個構造函數(shù) Student(),它的作用是給3個 private 屬性的成員變量賦值。在 main 函數(shù)中,我們根據(jù)構造函數(shù)創(chuàng)建了一個對象 stu;因為構造函數(shù)有參數(shù),所以創(chuàng)建對象時要相應地傳入實參,形式類似于函數(shù)調用。
讀者要注意:一旦在類中定義了構造函數(shù),那么創(chuàng)建對象時一定會被執(zhí)行;如果構造函數(shù)有參數(shù),創(chuàng)建對象時就要傳參。
另外,構造函數(shù)主要用來進行初始化,沒有返回值(有返回值沒有任何意義),這就意味著:
不管是聲明還是定義,函數(shù)名前面都不能出現(xiàn)返回值類型,即使是 void 也不允許;
函數(shù)體中不能有 return 語句。
默認構造函數(shù)
如果用戶自己沒有定義構造函數(shù),那么編譯器會自動生成一個默認的構造函數(shù),只是這個構造函數(shù)的函數(shù)體是空的,也沒有參數(shù),不執(zhí)行任何操作。比如上面的 Student 類,默認生成的構造函數(shù)如下:
1
|
Student(){} |
一個類,必須有構造函數(shù),要么用戶自己定義,要么編譯器自動生成。一旦用戶自己定義了構造函數(shù),不管它是 public 屬性的,還是 private、protected 屬性的,編譯器都不再自動生成。上面的 Student 類,只有一個構造函數(shù),就是我們自己定義的。
實際上,編譯器只有在必要的時候才會生成默認構造函數(shù),而且它的函數(shù)體一般不為空。默認構造函數(shù)的目的是幫助編譯器做初始化工作,而不是幫助程序員。這是C++的內部實現(xiàn)機制,這里不再深究,初學者可以按照上面說的“一定有一個空函數(shù)體的默認構造函數(shù)”來理解。
構造函數(shù)的重載
和普通成員函數(shù)一樣,構造函數(shù)是允許重載的。一個類可以提供多個構造函數(shù),讓用戶在創(chuàng)建對象時進行選擇,編譯器會根據(jù)創(chuàng)建對象時傳遞的參數(shù)來確定調用哪一個構造函數(shù)。也就是說:
只有一個構造函數(shù)會被執(zhí)行;
創(chuàng)建對象時提供的參數(shù)必須和其中的一個構造函數(shù)匹配,否則編譯錯誤。
一個構造函數(shù)重載的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#include <iostream> using namespace std; class Student{ private : char *name; int age; float score; public : //聲明構造函數(shù) Student(); Student( char *, int , float ); //聲明普通成員函數(shù) void setname( char *); void setage( int ); void setscore( float ); void say(); }; //定義構造函數(shù) Student::Student(){} Student::Student( char *name1, int age1, float score1){ name = name1; age = age1; score = score1; } //定義普通成員函數(shù) void Student::setname( char *name1){ name = name1; } void Student::setage( int age1){ age = age1; } void Student::setscore( float score1){ score = score1; } void Student::say(){ cout<<name<< "的年齡是 " <<age<< ",成績是 " <<score<<endl; } int main(){ //創(chuàng)建對象時初始化成員變量 Student stu1( "小明" , 15, 90.5f); stu1.say(); //調用成員函數(shù)來初始化成員變量的值 Student stu2; stu2.setname( "李磊" ); stu2.setage(16); stu2.setscore(95); stu2.say(); return 0; } |
運行結果:
1
2
|
小明的年齡是 15,成績是 90.5 李磊的年齡是 16,成績是 95 |
類中定義了兩個構造函數(shù),一個帶參數(shù)一個不帶參數(shù),它們是重載關系。當根據(jù)不帶參數(shù)的構造函數(shù)創(chuàng)建對象時,不需要傳參,成員變量不會被初始化,所以要調用成員函數(shù)來設置它們的值。
C++帶參數(shù)的構造函數(shù)
不帶參數(shù)的構造函數(shù)使該類的每一個對象都得到相同的初始值。
如果希望對不同的對象賦予不同的初始值,則需要使用帶參數(shù)的構造函數(shù),在調用不同對象的構造函數(shù)時,將不同的數(shù)據(jù)傳給構造函數(shù),以實現(xiàn)不同的初始化。
構造函數(shù)首部的一般格式為:
1
|
構造函數(shù)名(類型1 形參1, 類型2 形參2, …) |
由于用戶是不能調用構造函數(shù)的,因此無法采用常規(guī)的調用函數(shù)的方法給出實參。實參是在創(chuàng)建對象時給出的。創(chuàng)建對象的一般格式為:
1
|
類名 對象名(實參1, 實參2, …); |
【例】有兩個長方柱,其長、寬、高分別為12, 20, 25和10, 14, 20,求它們的體積。編寫一個基于對象的程序,在類中用帶參數(shù)的構造函數(shù)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#include <iostream> using namespace std; class Box { public : Box( int , int , int ); int volume( ); private : int height; int width; int length; }; //聲明帶參數(shù)的構造函數(shù)//聲明計算體積的函數(shù) Box::Box( int h, int w, int len) //在類外定義帶參數(shù)的構造函數(shù) { height=h; width=w; length=len; } int Box::volume( ) //定義計算體積的函數(shù) { return (height*width*length); } int main( ) { Box box1(12,25,30); //建立對象box1,并指定box1長、寬、高的值 cout<< "The volume of box1 is " <<box1.volume( )<<endl; Box box2(15,30,21); //建立對象box2,并指定box2長、寬、高的值 cout<< "The volume of box2 is " <<box2.volume( )<<endl; return 0; } |
程序運行結果如下:
1
2
|
The volume of box1 is 9000 The volume of box2 is 9450 |
可以知道:
帶參數(shù)的構造函數(shù)中的形參,其對應的實參在定義對象時給定。
用這種方法可以方便地實現(xiàn)對不同的對象進行不同的初始化。
用參數(shù)初始化表對數(shù)據(jù)成員初始化
上面介紹的是在構造函數(shù)的函數(shù)體內通過賦值語句對數(shù)據(jù)成員實現(xiàn)初始化。C++還提供另一種初始化數(shù)據(jù)成員的方法——參數(shù)初始化表來實現(xiàn)對數(shù)據(jù)成員的初始化。這種方法不在函數(shù)體內對數(shù)據(jù)成員初始化,而是在函數(shù)首部實現(xiàn)。
例中定義構造函數(shù)可以改用以下形式:
1
|
Box::Box( int h, int w, int len):height(h),width(w), length(len){ } |
這種寫法方便、簡練,尤其當需要初始化的數(shù)據(jù)成員較多時更顯其優(yōu)越性。甚至可以直接在類體中(而不是在類外)定義構造函數(shù)。