C++深入學習---建構函式的幾種應用場景
上一章對所有物件採用一致賦值的方法,即物件呼叫建構函式,設定初值。但是這樣有時候非常不靈活,因為對所有的物件,他們的initial value 都是一致的。有時候我們需要不同物件可能需要不同的初值,如此場景下,有了帶引數的建構函式。
1. 帶引數的建構函式
建構函式的一般格式為:
建構函式名(型別1 形參1,型別2 形參2,···)
定義物件的一般格式:
類名 物件名(實參1,實參2,···);
#include <iostream> using namespace std; class Box { public: Box(int h,int w,int l); // define constructor function int volume(); //class function //class function private: //private data members, unaccessable to public int height; int width; int length; }; Box::Box(int h,int w, int l) { height = h; width = w; length = l; } int Box::volume() { return (height * width * length); } int main() { Box box1(12,25,30); cout << "The volume of box1 is " << box1.volume() << endl; Box box2(15,30,21); cout << "The volume of box1 is " << box2.volume() << endl; return 0; }
Box::Box(int h,int w, int l)
{
height = h;
width = w;
length = l;
}
Box::Box既是通過賦值語句實現了物件的不同初始化工作。
另外還有一種就是用引數初始化表實現對資料成員的初始化。上面可以改成如下形式:
Box::Box(int h, int w, int l):height(h),width(w),length(l){}
這種寫法方便、簡練,尤其是當需要初始化的資料成員較多時更顯優越性。甚至可以直接在類體中(而不是類外)定義建構函式。很多程式設計師喜歡用這種方法初始化所有的資料成員。
2. 建構函式的過載
在一個類中可以定義多個建構函式,以便對類物件提供不同的初始化的方法,供使用者選用。這些建構函式具有相同的名字,而引數的個數或者引數的型別不相同。這稱為建構函式的過載
#include <iostream> using namespace std; class Box { public: Box(); Box(int h,int w,int l):height(h),width(w),length(l) {} // define constructor function int volume(); //class function //class function private: //private data members, unaccessable to public int height; int width; int length; }; Box::Box() { height = 10; width = 10; length = 10; } int Box::volume() { return (height * width * length); } int main() { Box box1; cout << "The volume of box1 is " << box1.volume() << endl; Box box2(15,30,20); cout << "The volume of box1 is " << box2.volume() << endl; return 0; }
注意:
(1)在呼叫函式時,不必給出實參的建構函式,稱為預設建構函式。也稱預設建構函式。例如題中的Box()。一個類只能有一個預設建構函式,否則系統無法辨別執行那一個建構函式。如果使用者未定義建構函式,系統自動提供一個預設的建構函式,但函式體是空的,不起任何初始化作用。
(2)建立物件是選用的是無參建構函式,那麼應該寫成
Box box1; //建立正確的預設建構函式
而不是
Box Box box1(); //錯誤的構造形式,不應該有括號,上面的語句並不是Box類的物件box1,而是一個普通的建構函式box1,此建構函式的返回值為Box型別。
記住:建構函式是不能被使用者顯示的呼叫的。 (3)儘管一個類中可以包含多個建構函式,但是對於每個物件來說,建立物件只執行一個建構函式,並非每個都執行。 下面再來看一段程式:#include <iostream>
using namespace std;
class Box
{
public:
Box(int h = 10,int w = 10,int l = 10); // define constructor function
int volume(); //class function
//class function
private: //private data members, unaccessable to public
int height;
int width;
int length;
};
Box::Box(int h, int w, int l)
{
height = h;
width = w;
length = l;
}
int Box::volume()
{
return (height * width * length);
}
int main()
{
Box box1;
cout << "The volume of box1 is " << box1.volume() << endl;
Box box2(15);
cout << "The volume of box1 is " << box2.volume() << endl;
Box box3(15,30);
cout << "The volume of box1 is " << box3.volume() << endl;
Box box4(15,30,20);
cout << "The volume of box1 is " << box4.volume() << endl;
return 0;
}
這是預設引數的建構函式。好處就是,即使呼叫建構函式時沒有提供實參值,不僅不會出錯,而且還確保按照預設的引數值對物件進行初始化。尤其是在希望對每一個物件都有相同的初始化狀況時用這種方法更方便,不需要輸入資料,物件按事先指定值初始化。說明:
(1)宣告建構函式時指定預設值。因為類的宣告是放在標頭檔案中,使用者可以到看的,而函式的定義是類的實現細節,使用者看不到。
(2)宣告建構函式時,形參名可以省略,可以寫成
Box (int = 10, int = 10, int = 10);
(3) 一個類只有一個預設的建構函式。如果同時定義了下面兩個建構函式,是錯誤的。Box(); //聲明瞭一個無參的建構函式
Box(int = 10, int = 10, int = 10); //聲明瞭一個全部的引數,都指定了預設值的建構函式。
因為在建立物件時,如果寫成 Box box1;
編譯系統無法識別哪個呼叫了建構函式,出現了歧異,編譯時報錯。
(4)在一個類中,如果定義了全是是預設引數的建構函式後,不能再定義過載建構函式。因為編譯時會出現歧異。因此,一般不能出現同時使用建構函式的過載和有預設引數的建構函式。