資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010
大綱 使用類別(Class)建立資料結構 使用繼承(Inheritance)建立資料結構
類別(Class) 類別class是C++中用來封裝資料的關鍵字,當您 使用類別來定義一個物件(Object)時,您考慮這個 物件可能擁有的「屬性」(Property)與「方法」 (Method)成員 屬性是物件的靜態描述 方法是可施加於物件上的動態操作 您使用類別定義出這個物件的規格書,之後就可 依這個規格書製作出一個個的物件實例,並在製 作過程中設定個別物件的專屬特性資料。 要訣: 屬性(該類別的變數)要存放的資料 (每個物件有自己的屬性) 方法(該類別的函式)寫要執行的程式 (用方法控制屬性)
如何設計類別? 思考 (以功能角度) 進階思考 (以使用者角度) 每個物件需要什麼資料? 宣告屬性 每個物件需要什麼資料? 宣告屬性 每個物件需要什麼方法來操作資料? 設計方法 進階思考 (以使用者角度) 如何讓使用類別宣告物件的人方便簡單使用。 如何避免使用類別宣告物件的人因用到不該用的資料而產生 錯誤。
類別(Class) 宣告一個類別 (類似定義一個結構struct) 語法: class 類別名稱 { public: 類別名稱(); //建構式, 用來做物件的初始化 ~類別名稱(); //解構式, 用來做物件的善後工作 公開的方法或屬性; protected: // 只有在同一繼承架構中可以使用的資料 受保護的方法或屬性; private: // 只有在此類別中可以使用的資料 私有的方法或屬性; };
資料的權限 三種資料的權限設定 在類別封裝時,有一個基本原則是:資訊的最小 化公開。如果屬性可以不公開就不公開。 public: 「公開成員」表示以下所定義的成員可以使用物件名 稱直接被呼叫,稱之為 protected: 「受保護成員」表示以下所定義的成員只可在同 一繼承架構下之類別中可以使用。 private:「私有成員」表示以下所定義的成員只可在自己的類 別中可以使用。 在類別封裝時,有一個基本原則是:資訊的最小 化公開。如果屬性可以不公開就不公開。 如果要取得或設定物件的某些屬性,也是儘量透 過公開方法成員來進行。
建構式與解構式 建構式(Constructor) 解構式(Destructor) 在定義類別時,您可以使用「建構函式」來進行物件的初始 化。 在物件釋放資源之前,您也可以使用「解構函式」來進行一 些善後的工作。
類別的方法之描述 實作一個類別方法的內容(類似寫一個函式) 除了寫在類別定義中, 也可拿到類別定義以外的地 方描述 語法: 資料型態 類別名稱::方法名稱( 參數1, 參數2, … ,參數n ) { 程式碼; }
物件的產生與使用 使用類別定義物件 (類似定義一個變數) 語法: 物件可透過 . 來使用或存取該方法或屬性(類似C語 言的結構struct) 類別名稱 物件名稱; 類別名稱 物件名稱( 參數1, 參數2, … , 參數n ); 物件可透過 . 來使用或存取該方法或屬性(類似C語 言的結構struct) 若為物件指標,可透過 ->來使用或存取該方法或 屬性
範例:製作一個2D座標類別 製作以下程式範例: Point2D.h Point2D.h: 定義類別 Point2D.cpp: 設計類別的方法 main.cpp: 主程式 Point2D.h class Point2D { public: Point2D(); //建構式 Point2D(int x, int y); //可傳入初始值的建構式 void set(int x, int y); //設定點座標 void print(); //印出點座標 protected: int X; //X座標 int Y; //Y座標 };
範例:製作一個2D座標類別 Point2D.cpp main.cpp #include <iostream> using namespace std; #include "Point2D.h" Point2D::Point2D() { X = 0; Y = 0; } Point2D::Point2D(int x, int y) X = x; Y = y; void Point2D::set(int x, int y) void Point2D::print() cout << "(" << X << "," << Y << ")" << endl; #include <iostream> using namespace std; #include "Point2D.h" int main() { Point2D p1; Point2D p2(5, 10); p1.set(20, 30); p1.print(); p2.print(); return 0; }
範例: C++鏈結串列 將第二章之鏈結串列範例改用C++之類別實作 class LinkedList node * head node (LinkedList.h , LinkedList.cpp , LinkedList_main.cpp) class LinkedList node * head node node node 10 20 30 int data node * NULL next
練習: C++樹狀結構 將第六章之二元搜尋樹範例改用C++之類別實作 class BinarySearchTree root node 5 (BinarySearchTree.h , BinarySearchTree.cpp , BinarySearchTree_main.cpp) class BinarySearchTree root node 5 data left right 4 6 NULL NULL NULL NULL
大綱 使用類別(Class)建立資料結構 使用繼承(Inheritance)建立資料結構
繼承(Inheritance) 「繼承」(Inheritance)是物件導向程式設計的 一種進階觀念,繼承就是物件的再利用,當定義 好一個類別後,其他類別可以繼承這個類別的成 員資料和函數。 語法: class 子類別名稱: 繼承權限 父類別名稱 { … }; 在繼承的關係中 被繼承的類別: 「父類別」(Parent class)或「基礎類別」(Base class), 繼承父類別的類別: 「子類別」(Child class)或「衍生類別」(Derived class)
範例:製作一個3D座標類別 製作以下程式範例: Point3D.h Point2D.h: 定義2D類別 (使用之前的Point2D範例) Point2D.cpp: 設計2D類別的方法 (使用之前的Point2D範例) Point3D.h: 定義3D類別 Point3D.cpp: 設計3D類別的方法 main.cpp: 主程式 Point3D.h #include "Point2D.h" class Point3D: public Point2D { public: Point3D(); //建構式 Point3D(int x, int y, int z); //可傳入初始值的建構式 void set(int x, int y, int z); //設定點座標 void print(); //印出點座標 private: int Z; //Z座標 };
範例:製作一個3D座標類別 Point3D.cpp main.cpp #include <iostream> using namespace std; #include "Point3D.h" Point3D::Point3D() { Z = 0; } Point3D::Point3D(int x, int y, int z) : Point2D(x, y) Z = z; void Point3D::set(int x, int y, int z) Point2D::set(x, y); void Point3D::print() cout << "(" << X << "," << Y << "," << Z << ")" << endl; #include <iostream> using namespace std; #include "Point3D.h" int main() { Point3D p1; Point3D p2(5, 10, 20); p1.set(20, 30, 40); p1.print(); p2.print(); return 0; }
範例:C++堆疊 使用C++鏈結串列以繼承方式實作堆疊 class Stack class LinkedList node * head (Stack.h , Stack.cpp , Stack_main.cpp) class Stack class LinkedList node * head node node node 10 20 30 int data node * NULL next
練習:C++佇列 使用C++鏈結串列以繼承方式實作佇列 class Queue node * rear class LinkedList (Queue.h , Queue.cpp , Queue_main.cpp) class Queue node * rear class LinkedList node * head node node node 10 20 30 int data node * NULL next