自定義結構
自定義結構為一些成員元素(資料)的組合體,在 C 有 struct , C++ 有 struct 和 class , C 和 C++ 的 struct 是不同的,以下講解:
C 的 struct
- 定義:
{}之間存放成員元素,成員元素可以示指標或陣列,}之後要加上;。 - 宣告:宣告可在定義時宣告(
Line 6),也可以獨立宣告一行 (Line 8-10),相似地,可以宣告為指標或是陣列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
C++ 的 struct 和 class
C++ 的 struct 和 class 導入物件導向的概念,除了成員元素,還可定義成員函式。獨立宣告時,不用在前面加上 struct 和 class 。
C++ 的 struct 和 class 的差異在於成員的預設存取權限,有 public 、 protected 、 private 三種權限, strcut 成員預設為 public , class 則是 private 。
public: 所有函式可存取。protected: 成員函式、friend類別成員或函式,以及衍生類別可存取。private: 成員函式及friend類別成員或函式可存取。
1 2 3 4 5 6 7 | |
friend 關鍵字
每個人社群中的好友,可以看到自己發佈的私人文章, friend 就同如社群中的好友,提供 friend 類別或函式存取該結構的元素。
1 2 3 4 5 6 7 8 | |
衍生類別
衍生類別是物件導向的概念,如果 B 是一種 A , B 就是 A 的衍生類別, A 就是 B 的基礎類別。
例如「汽車」是一種「交通工具」,那麼「汽車」就是「交通工具」的衍生類別,「交通工具」就是「汽車」的基礎類別。
訪問元素
對於一般變數 var ,用 var.name 。
對於指標變數 ptr ,用 ptr->name 或 (*ptr).name 。
覆載 (Override) 和多載 (Overload)
覆載 (Override) 是指在衍生類別重新改寫同名寫「參數相同」的函式。
多載 (Overload) 是指在重新改寫同名寫「參數不同」的函式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
建構函式 (Constructor)、解構函式 (Destructor)
建構函式結構的名稱相同,是用來初始化結構裡的資料,如果沒有任何建構函式,會自動產生一個無參數的預設建構函式。然而,如果有一個帶參數的建構函式,就不會自動產生一個無參數的預設建構函式,這時候要寫一個不帶任何參數的運算函式,否則可能導致程式在編譯時發生錯誤。
解構函式的名字形式為 ~結構的名稱 ,在變數離開作用域時運作,不寫的話也是會有預設解構函式,在程式比賽中絕大部分的狀況,不用特別寫解構函式。
建構函式和解構函式的存取權限必為 public 。
多載運算子(Operator overloading)
C/C++ 定義了各種運算子,自定義結構根據需求可以多載運算子。在競賽中,常需要作排序而需要多載小於運算子( < )。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
長度
結構的長度,並非為所有元素相加, C/C++ 的結構長度配置會進行「對齊的最佳化」。struct 會分成很多塊存放,每一塊會是最大元素的長度為對齊基準,元素會依宣告的順序擺放,連續的元素會放在同一塊,如果不夠空間擺放才會放在下一塊。
以下例子作為說明,在這裡,我們 sizeof 這個運算子求出結構的長度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
Data1 和 Data2 當中最大元素長度為 4 ( int )。 Data1 ,用了 塊來存 個 struct ,第一塊存 char ch1 ,第二塊存 int i ,第三塊存 char ch2 ,因此長度為 ; Data2 ,用了 塊來存 個 struct ,第一塊存 char ch1 和 char ch2 ,第二塊存 int i ,因此長度為 。
為什麼要用自定義結構
資料存放有很多種方法,可以利用開多個陣列來取代自定義結構,但有些操作會直接將資料移動,包含排序和刪除,如果用多個陣列儲存,需要確保每個陣列的資料都被正確的移動;使用結構,就不用去維護這件事情。
再來是多個結構可能會有相同名稱的成員元素。例如 apple 和 banana,它們都有一個成員元素 price,如果用多個陣列儲存,它們不能共用同一個陣列 price[] ,要寫成 priceOfApple 和 priceOfBanana ;如果用結構,就可以讓不同結構擁有相同名稱的成員元素(例如 a.price 和 b.price ) 來區分。