建構子 Constructor
在 類別 Class 中,我們介紹了什麼是類別以及該如何創造一個類別,其中我們講到了建構子,但我們沒有細講什麼是建構子。
建構子是創造一個實體物件必備的要件之一。接下來,讓我們仔細來討論這個重要的要件吧!
什麼是建構子
我們可以把建構子看作是一個類別中特別的函數,這個特別的函數會在物件被創造時「自動」執行。
當一個物件被創造時,編譯器會在該類別中尋找可以匹配的建構子。如果有找到可以匹配的建構子,那麼物件就會被創建。否則程式碼就會報錯。
在建構子中,通常有兩件事會被執行:
- 初始化類別中的參數
- 執行其他函數
初始化類別中的參數比較直觀,這邊就不贅述。
在執行其他函數中,常見的功能可能會是檢查參數值、讀取文件等等。這些步驟常常是物件創建時需要馬上執行的。
如何創建
建立建構子其實很簡單,只有兩個準則需要遵守。
- 建構子名稱必須和類別名稱相同
- 建構子沒有回傳值
也就是說,如果有一個類別叫做 Object
,而且不接受任何參數,那麼這個類別跟他的建構子就會長這樣:
class Object { Object() {} };
我們可以注意到建構子的本體,也就是大括弧 {}
中沒有任何 return
,並且函數 Object()
前也沒有定義回傳型態。
實際範例
了解了建構子的意義以及如何創建後,我們來看幾個實際範例
簡單範例class Object { private: int m_x; int m_y; public: Object(int x, int y) : m_x(x), m_y(y) { std::cout << "呼叫建構子:Object(" << x << ", " << y << ")" << std::endl; } void print() const { std::cout << "Object(" << m_x << ", " << m_y << ")" << std::endl; } }; int main() { Object obj = Object(3, 4); obj.print(); return 0; }
在這個例子中,我們創建了一個叫做 Object
的類別,這個類別需要兩個參數才可以創立。
注意看這裡我們是如何初始化類別中的參數的。
Object(int x, int y) : m_x(x), m_y(y)
這個技巧叫做 Member Initializer List,單純是用來初始化類別參數的。
但是如果你想要寫在建構子本身內也可以達到同樣的效果,比如說:
Object(int x, int y) { m_x = x; m_y = y; }
但是在近代的 C++ 中,使用 Member Initializer List 才是比較推薦的用法,這是考慮到執行效能的因素。可以參考 Stack Overflow 這篇 Why should I prefer to use member initializer lists 的討論。
以上的程式碼在執行後會有這樣的輸出:
呼叫建構子:Object(3, 4) Object(3, 4)多個建構子
沒錯!一個類別可以有好幾個建構子!
為什麼?你想喔,類別是建造物件的範本,而我們可能會想讓這個物件擁有不同的特徵。
就好比 10 個人都訂購了馬自達 CX5 的車,雖然都是 CX5,但是每個人的要求可能不一樣。有的人可能會想要有天窗、有的人可能會想要車子是灰色的、有的人可能想要有加熱座椅。
不同的建構子就是讓我們可以用不同的方式建構出實體物件。
我們直接來看個例子:
class Object { private: int m_x; int m_y; public: Object() { std::cout << "呼叫建構子:Object()" << std::endl; } Object(int x) : m_x(x) { std::cout << "呼叫建構子:Object(" << x << ")" << std::endl; } Object(int x, int y) : m_x(x), m_y(y) { std::cout << "呼叫建構子:Object(" << x << ", " << y << ")" << std::endl; } }; int main() { Object obj1 = Object(); Object obj2 = Object(3); Object obj3 = Object(3, 4); return 0; }
在上面的例子中,我們可以看到有三個建構子,分別接收 0、1、2 個參數。
在主程式中,我們則利用不同的建構子建立了三個實體物件,我們可以從輸出看到的確不同的建構子被呼叫了!
呼叫建構子 Object() 呼叫建構子 Object(3) 呼叫建構子 Object(3, 4)
總結
這章我們了解了什麼是建構子 Constructor,它的作用以及該如何運作。
然而建構子的概念遠遠不止這樣,更進階的還有 Copy Constructor、Copy Assignment Operator 等等。
但這章我們講大概念就行了!以後有空再講更進階的概念吧!
希望有讓你們學到東西囉~