【C++ 筆記】建構子(Constructors) - part 18
【C++ 筆記】建構子(Constructors) - part 18
很感謝你點進來這篇文章。
你好,我並不是什麼 C++、程式語言的專家,所以本文若有些錯誤麻煩請各位鞭大力一點,我極需各位的指正及指導!!本系列文章的性質主要以詼諧的口吻,一派輕鬆的態度自學程式語言,如果你喜歡,麻煩留言說聲文章讚讚吧!
建構子(Constructors)
建構子(Constructors),又稱建構函數、建構式,為一種特別的 class members,每次實例化該類別的物件時,編譯器都會呼叫建構子(表示每次建立物件都會用到此函數)。建構子與 class 具有相同的名稱,並且可以在 class 中進行內部定義或外部定義。
另外建構子也不會回傳任何型態,也不會回傳 void。
:::success
可以想像建構子就是做初始化的動作。
:::
在 C++ 中,共有下列四種建構子:
- 預設建構子(Default Constructors)
- 參數化建構子(Parameterized Constructors)
- 複製建構子(Copy Constructors)
- 移動建構子(Move Constructors) -> 此篇不談
以下是一個練習範例(展示預設建構子),新手適用的建構子教學:
1 |
|
輸出結果:
1 | 預設建構子被呼叫了 |
參數化建構子(Parameterized Constructors)
就是帶有參數的建構子,因為他本身還是個函數嘛,以下是個範例:
1 |
|
輸出結果:
1 | 品牌: Toyota, 車型: Corolla, 出廠年份: 2020 |
複製建構子(Copy Constructors)
複製建構子(Copy Constructor)是一種特殊的建構子,用來建立一個新物件,並以同型態的另一個已存在的物件來初始化它。
格式:
1 | classname (const classname &obj) { |
ClassName:類別名稱。
const ClassName& obj:以參考方式傳遞的另一個物件,通常使用 const 使源物件不被修改。
const 看你要不要加,但加它是為了讓程式設計師不會錯誤地修改 obj。
這個 obj 就是 object,物件的意思。
複製建構子用於以下三種情形:
- 透過使用另一個同型態的物件來初始化新建立的物件。
- 複製物件把它當作參數傳遞給函數。
- 複製對象,並從函數回傳這個對象。
若無明確定義複製建構子,編譯器會自動產生,該建構子會執行淺層複製(Shallow Copy):
- 將 class 中的每個成員的值逐一複製。
- 若 class 中包含指標成員,預設複製建構子會直接複製指標的地址,導致兩物件共享記憶體區域。
簡言之,淺複製只會複製指針,而不會複製他實際上的”源頭”,若刪除原本的物件,就可能導致空指針(NULL Pointer)。
與淺複製相反的,就是深層複製(Deep Copy),要使用深層複製,就是直接將 Copy Constructor 明確定義出來。
另外 Deep Copy 會為新物件分配獨立的記憶體空間,並複製資料內容與指標。
以下是一個範例:
1 |
|
Source:https://www.geeksforgeeks.org/copy-constructor-in-cpp/
輸出結果:
1 | a1's x = 10 |
透過上述範例,可發現我們並未定義「建構子」,但卻能夠使用同一個類別現有的物件來建立一個物件。那此時 C++ 編譯器就會建立一個簡單的複製建構子,也稱隱式複製建構子(implicit copy constructor)。
以下是一個範例,當我們定義 Copy Constructor:
1 |
|
Source:https://www.geeksforgeeks.org/copy-constructor-in-cpp/
輸出結果:
1 | a1's x = 10 |
以上程式碼第十行,A(){}; 為定義一個預設建構子,但他是空的。那他有什麼屁用呢?
若刪掉此行,則會因為 class 中已定義了一個複製建構子 A(A& t),編譯器將不再自動產生預設建構子。所以,A a1; 物件會無法建立,編譯器直接報錯。
這是先後順序問題,你要先建立物件才能用 Copy Constructor,因此需要預設建構子為基礎。
以下是個範例,有關於深層複製(Deep Copy):
1 |
|
Source:https://www.geeksforgeeks.org/copy-constructor-in-cpp/
輸出結果:
1 | GeeksQuiz |
此範例使用到了 new、delete 運算子,這兩個運算子的意義分別是「自行對記憶體配置」、「自行刪除掉記憶體」。
有關 new、delete 運算子的使用上,是要非常小心的,若一直用 new 一直給記憶體資源,而不用 delete 刪除的話,那麼記憶體會吃滿。
詳情可至此網站了解:https://openhome.cc/Gossip/CppGossip/newDelete.html
第十二行中,用到了解構子的語法:~String() { delete[] s; }。
:::success
解構子(Destructor),語法就是用一個波浪符號 ~ 後面加上類別名稱,與建構子宣告方式類似。它不會回傳任何值,也不能帶有任何參數。解構子有助於在跳出程式(例如關閉檔案、釋放記憶體等)前釋放資源。
:::
那第十二行就是在說當離開作用域或程式結束時,會自動刪除掉 s 這個成員。
總結
建構子(Constructors) 是 C++ 類別中特別的成員函數,每次建立物件時都會自動被呼叫,用於初始化物件。
:::success
建構子與類別名稱相同,沒有回傳值。 -> 非常重要
:::
C++ 提供了四種建構子:
- 預設建構子(Default Constructor):不帶參數,將物件設定預設值。
- 參數化建構子(Parameterized Constructor):允許在建立物件時傳入參數進行初始化。
- 複製建構子(Copy Constructor):用於建立新物件,並以現有的同型態物件初始化它。若未定義,編譯器會使用淺層複製(Shallow Copy),但當類別包含動態記憶體分配時,應使用深層複製(Deep Copy)來避免記憶體錯誤。
- 移動建構子(Move Constructor)->本篇不談
Copy Constructor Application:
- 以現有物件初始化新物件。-> 如:
myClass a2 = a1 - 當物件作為參數傳遞給函數時。
- 當函數回傳物件時。
若類別包含指標成員,應用深層複製確保每物件有獨立記憶體區域,避免記憶體共享導致的錯誤。
參考資料
Copy Constructor in C++ - GeeksforGeeks


