1 / 130

第十章

第十章. 定義類別和物件實體. 本章學習目標:. 宣告類別後,類別內必須包含資料成員(屬性)和成員函數(方法)。 類別和存取權限的關係,並將封裝的概念轉化為實作內容。 將物件初始化的建構式,及建構式的種類。 類別也有成員,包含了靜態屬性和靜態成員函數。 使用 this 指標來指向物件本身。. 類別為何是物件原型,物件為何是類別的實體化?本將利用實作方式來說明:. 10-4-1 預設建構式 10-4-2 複製建構式 10-4-3 型別轉換建構式 10-4-4 組合物件建構式. 10-4 建構式的種類. 10-1-1 產生類別

gelsey
Download Presentation

第十章

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十章 定義類別和物件實體

  2. 本章學習目標: • 宣告類別後,類別內必須包含資料成員(屬性)和成員函數(方法)。 • 類別和存取權限的關係,並將封裝的概念轉化為實作內容。 • 將物件初始化的建構式,及建構式的種類。 • 類別也有成員,包含了靜態屬性和靜態成員函數。 • 使用this指標來指向物件本身。 類別為何是物件原型,物件為何是類別的實體化?本將利用實作方式來說明:

  3. 10-4-1 預設建構式 10-4-2 複製建構式 10-4-3 型別轉換建構式 10-4-4 組合物件建構式 10-4 建構式的種類 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-3 宣告成員函式 10-1-4 使用範圍解析運算子 10-1-5 建立物件實體 10-1 建立類別和物件 10-5-1 認識類別成員 10-5-2 靜態屬性 10-5-3 靜態成員函數 10-5 類別成員 10-2-1 存取權限 10-2-2 資料保護 10-2 資料封裝 10-6-1 物件指標 10-6-2 動態配置指標 10-6-3 this指標的用途 10-6 物件與指標 10-3-1 物件的初始化 10-3-2 清除物件 10-3-3 物件的生命週期 10-3 使用建構式 章節目錄

  4. 10-4-1 預設建構式 10-4-2 複製建構式 10-4-3 型別轉換建構式 10-4-4 組合物件建構式 10-4 建構式的種類 10-5-1 認識類別成員 10-5-2 靜態屬性 10-5-3 靜態成員函數 10-5 類別成員 10-2-1 存取權限 10-2-2 資料保護 10-2 資料封裝 10-6-1 物件指標 10-6-2 動態配置指標 10-6-3 this指標的用途 10-6 物件與指標 10-3-1 物件的初始化 10-3-2 清除物件 10-3-3 物件的生命週期 10-3 使用建構式 章節目錄

  5. 10-1 建立類別和物件 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-4 使用範圍解析運算子 10-1-3 宣告成員函式 10-1-5 建立物件實體 章節目錄

  6. 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-4 使用範圍解析運算子 10-1-3 宣告成員函式 10-1-5 建立物件實體 章節目錄 10-1 建立類別和物件

  7. 10-1 建立類別和物件 • 對於物件導向的觀念有所認識之後,我們要以C++程式語言的觀點來深入探討類別和物件的實作,透過物件導向程式設計(OOP)的運作,更進一步瞭解!

  8. 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-4 使用範圍解析運算子 10-1-3 宣告成員函式 10-1-5 建立物件實體 章節目錄 10-1 建立類別和物件

  9. 10-1-1 產生類別 • 我們已經知道「類別」(class)是物件的原型,在使用物件之前先熟悉類別的建立。語法如下:

  10. 為關鍵字,用來定義類別 class • 建立類別使用的名稱,同樣地也必須遵守識別字的命名規範 • 此外,類別名稱只是用來定義類別,必須等到類別實體化之後才會取得記憶體空間的配置 類別名稱 private public protected • 關鍵字,用來設定資料成員的存取權限 資料成員 (Data Member) 成員函式 (Member Function) • 資料成員負責儲存資料的變數 • 定義類別時,存取權限必須存放在區塊{}內,結束時必須加上分號「;」 類別(class)語法解說:

  11. 類別的敘述表示 • 瞭解類別的宣告後,如果要利用程式碼來撰寫一個類別,寫法如下: 此處我們宣告一個car類別

  12. 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-4 使用範圍解析運算子 10-1-3 宣告成員函式 10-1-5 建立物件實體 章節目錄 10-1 建立類別和物件

  13. 10-1-2 宣告資料成員 • 完成類別的宣告後,得定義資料成員(屬性),語法如下: • 其實這和第二章所介紹的宣告變數方法相同,只是此處宣告的對象是資料成員名稱!若要建立一個汽車的類別,敘述如下: 我們在car類別加入二個資料成員,它們的存取權限是public,表示這些資料成員皆能自由存取。

  14. 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-4 使用範圍解析運算子 10-1-3 宣告成員函式 10-1-5 建立物件實體 章節目錄 10-1 建立類別和物件

  15. 10-1-3 宣告成員函式 • 在物件導向程式語言中,除了要有屬性(資料成員),還得加上方法(成員函式) • 因此還必須在類別內宣告成員函式,語法如下: • 其實大家已經發現,這和第六章介紹的函數相同,要有回傳資料型別、函式名稱和參數串列。 • 如果要在car類別內加入成員函式,程式碼如下:

  16. 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-4 使用範圍解析運算子 10-1-3 宣告成員函式 10-1-5 建立物件實體 章節目錄 10-1 建立類別和物件

  17. 10-1-4 使用範圍解析運算子 • 當我們在類別裡定義了成員函式的原型後,倘若要在類別定義範圍外使用成員函式時,必須利用範圍解析運算子「::」指定成員函數所隸屬的類別。語法如下: • 延續car類別範例,如果要在car類別之外使用setSpeed()成員函數,寫法如下:

  18. 10-1-1 產生類別 10-1-2 宣告資料成員 10-1-4 使用範圍解析運算子 10-1-3 宣告成員函式 10-1-5 建立物件實體 章節目錄 10-1 建立類別和物件

  19. 10-1-5 建立實體物件 • 宣告類別後,若要將類別實體化,就得建立物件 • 不過,對於初學者來說,OOP的類別和物件非常容易混淆,如果我們把類別視為「自訂的資料型別」,物件就是類別中所宣告的變數! • 如此一來,只要定義類別,並將物件當作基本資料型別的變數來處理就可以了。 • 如何建立一個物件,語法如下:

  20. 物件的敘述 • 倘若要建立一個car類別的物件,敘述如下: 從OOP的觀點來看,表示將car類別實體化,建立一個march物件。

  21. 成員的存取 • 產生物件後 • 物件的狀態如何被改變? • 如何利用方法來進行操作? • 必須利用「.」運算子來存取類別中所產生物件的成員,語法如下: 利用範例「car.vcproj」來說明類別的宣告和物件實體的建立。

  22. 範例:car.vcproj(1)

  23. 範例:car.vcproj(2)

  24. 執行程式:car.vcproj • 利用結構的觀念來定義:學生成績和儲存輸入資料。 • 第10~14行定義學生成績的結構,包含以字元陣列來處理的學生姓名、儲存學生成績和成績等級三種結構欄位。 • 第17~19行的SaveData結構用來諸存輸入的資料,最大筆數是20筆。 • 第25~42行為主程式,利用第28~41行while迴圈來判斷使用者是否要新增資料。而31~40行利用switch來進行條件選擇。使用者按下A表示要新增資料,按下E表示結束新增的動作。

  25. 範例「car.vcproj」的思考 • 範例「car.vcproj」說明兩件事: • car類別可依據實際需求來產生不同狀態的物件。 • 每個物件的狀態是獨立的,當march物件的狀態改變時並不會影響marchwin物件。

  26. 章節目錄 10-2 封裝資料

  27. 10-2 資料封裝 • 封裝的作用是讓使用者利用介面來簡化操作程序 • 大家可以想像一下!如果搭乘的電梯缺少控制面板是什麼情形? • 使用者可能得自己計算電動機的電流,才能讓曳引機帶動到欲前往的樓層距離。 • 但是若以OOP的觀點來看,只要將控制面板上的移動方法設定好,能與電梯物件的某個屬性對應,搭乘電梯就非常簡便。 • 一般而言,將封裝的概念應用到程式設計上,就是類別內的資料成員只能透過類別內的成員函數來存取。

  28. 10-2-1 存取權限 章節目錄 10-2 封裝資料

  29. 10-2-1 存取權限 • 在類別內如何以成員函數來存取資料成員!當我們宣告類別時,共有三個不同等級的存取權限: • public、private和protected。 • 三者的作用以下表10-1表示:

  30. private • 表示任何類別皆可存取,適用於對外公開的資料 • 當物件的資料不想對外公開時,只能被類別內的成員函數來存取,或是同類別的其他物件也能存取該物件的資料 public protected • 只有該類別或繼承這類別的子類別的物件(會在第11章繼續討論) 存取權限的範圍

  31. 利用方法封裝物件 • 我們在第九章討論過「封裝」概念(參考9-2-1資料抽象化)!在物件導向技術的世界裡,為了達到「資訊隱藏」目的,可以透過「方法」來封裝物件的屬性。 • 存取權限的作用能讓物件掌握成員,控制物件在被允許的情形下才能讓外界使用。 • 為了保護物件的屬性不被外界其他類別所存取,通常會將資料成員宣告為private; • 再利用成員函數做為物件和其他物件的介面,因此常宣告為public。 • 有了這樣的概念,我們再回頭來看看第一個範例「car.cpp」,並將資料成員的存取權限要更改為private,再透過成員函數來存取這些資料成員,如範例upcar.vcproj所示。

  32. 巢狀結構的存取 • 若要存取學生成績中的姓名,其敘述如下: • 這表示要先透過處理資料的stu_data結構變數,才能進一步存取。利用SaveData結構中宣告的db_rds欄位(為student結構變數)進行學生成績結構中的姓名欄位存取。

  33. 範例:upcar.vcproj(1)

  34. 範例:upcar.vcproj (2)

  35. 範例:upcar.vcproj (3)

  36. 範例:upcar.vcproj (4)

  37. 執行程式:upcar.vcproj 此範例說明「封裝」的作用,將UpCar類別的color、engi屬性設為private,然後利用類別本身的成員函數setColor()來存取color屬性,setEngi()來存取engi屬性。從另一個觀點來看,透過相對應的「方法」才能改變物件的「屬性」。

  38. 程式解說:upcar.vcproj • 第7~16行定義UpCar類別及相關的資料成員和成員函數。 • 第24~35行定義setColor()成員函數,當使用者選擇color屬性時,執行顏色的設定。此處利用switch/case敘述來接受使用者選擇的顏色。 • 第38~43行定義setEngi()成員函數,當使用者選擇engi屬性時,執行排氣量的設定。利用if進行條件判斷來顯示排氣量。 • 第46~63行是主程式,第50行先讓使用者選擇車款,然後再選擇顏色和排氣量。這些屬性設定會改變march和marchwin物件的狀態。

  39. 10-2-1 存取權限 10-2-2 資料保護 章節目錄 10-2 封裝資料

  40. 10-2-2 資料保護 • 還記得const這個關鍵字,在第2章曾討論過:當資料的值不想被改變時,可利用const將資料的值宣告為「常數」。 • 若從資料保護的觀點來看 • 存取控制只是讓資料存取有所依據 • 想要更嚴謹的保護資料,可透過const將類別中的成員函數、物件再加上一道保護鎖!

  41. 常數函數 • 所謂常數函數是一個「唯讀函數」(Read-only function),表示函數在執行時無法改變物件的狀態。語法如下: 如何讓成員函數形成常數函數,就是在參數串列之後,進入區塊之前,加入const關鍵字。透過範例「ConstFunc.vcproj」說明成員函數變成常數函數執行時產生錯誤的情形!

  42. 範例:ConstFunc.vcproj(1)

  43. 範例:ConstFunc.vcproj(2)

  44. 執行程式:ConstFunc.vcproj(錯誤) • 第6~11行宣告class類別,其中第8行成員函數setHeight()因為加上const關鍵字形成常數函數,第10行height為資料成員。 • 第17~19行定義getHeight()成員函數,將取得的資料成員height利用return敘述回傳。 • 第21~25行是主程式,第22行宣告一個Hobbit物件,第23行呼叫setHeight()成員函數進行參數傳遞,第24行利用getHeight()成員函數來輸出結果。

  45. 常數函式的特性 • 第18行為什麼會產生錯誤?這是一個很典型的OOP程式 • 將height屬性的存取權限設為private • 利用setHeight()成員函數來修改屬性 • 再透過getHeight()成員函數回傳物件改變後的狀態 • 問題就出自於setHeight()成員函數已經被宣告為常數函數,表示它不能修改物件的屬性,因此const很明顯放錯位置,我們將程式碼修正。

  46. 部份程式碼:ConstFuncMd.cpp

  47. 執行程式:ConstFuncMd.cpp • 利用setHeight()成員函數來修改屬性,而以getHeight()成員函數回傳改變後的物件狀態,所以將getHeight()成員函數宣告為常數函數,確保回傳過程中屬性值不會再被改變。 • 所以將第7行的函式原型和第13~15行定義getHeight()成員函數加上const關鍵字,而把setHeight()成員函數原有的const關鍵字刪除即可讓程式輸出正確結果。

  48. 常數物件 • 當物件被宣告為常數物件時,表示任何成員函數都無法改變物件的屬性。 • 此時,常數物件呼叫成員函數時,只能呼叫常數函數來確保物件的屬性不會被改變。 • 我們延續上一個範例來說明常數物件。

  49. 部份程式碼:ConstFuncMd.cpp

  50. 執行程式:ConstFuncMd.cpp 顯示錯誤訊息:ConstFuncMd.cpp(25) : error C2662: 'people::setHeight' : 無法將'this' 指標從'const people' 轉換成'people &'轉換遺失限定詞 • 範例中原有的內容並沒有改變,在主程式中第22行宣告flores為常數物件,然後在第25、26行分別呼叫了setHeight()和getHeight()二個成員函數 • 因為flores是常數物件,所以只能呼叫常數函數getHeight() • 當常數物件呼叫了setHeight()成員函數時會顯示錯誤訊息

More Related