衍生类别的定义.PPT

衍生类别的定义

物件導向程式語言講義 靜宜大學資訊管理學系 蔡奇偉 副教授 Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別 virtual 成員函式 RTTI (Run-time Type Information) 前言 衍生類別的定義 存取控制 單一繼承 public, protected, 和 privated 基底類別 Virtual Functions 宣告 virtual 函式 Pure Virtual Functions Abstract Classes RTTI (Run-time Type Information) dynamic_cast typeid 從以上的比較我們得知:對基底類別成員的存取,以 public 的限制最少、protected 次之、而 private 最多。此外,只有 public 的繼承方式允許在非成員的函式中,把衍生類別型態的指標轉換成基底類別型態的指標。由於這些原因,public 的繼承方式是最常用來定義基底類別的子類型(subtype)。如果我們想把基底類別當成 implementation 內部的一個類別,不希望外界直接地使用它,最好使用 protected 和 private 的繼承方式,其中又以 private 的隔離效果比 protected 來得大。 假定我們有如右邊所示的類別繼承關係。由於資料成員多寡不一,每個類別因此各自定義了一個 print() 成員函式,用來列印相關的員工資料。 class Employee { public: void print (); // … }; class Manager : public Employee { public: void print (); // … }; class Director : Manager { public: void print (); // … }; 假定你想寫一個函式能夠列印任何一類員工的資料。由於 Manager 和 Director 都屬於 Employee 類別,因此你可能認為以下的函式就可以達到這個目的: void print_emp (Employee *e) { e-print(); } 其實不然。原因是:e 是 Employee 型態的指標,所以不論傳進來的引數型態是 Employee、 Manager、或 Director,e-print() 永遠是呼叫 Employee 的成員函式 print()。 你可以在 Employee 類別中,加入一個儲存員工類型的資料成員來解決前述的問題。譬如: class Employee { public: enum emp_type {EMPLOYEE, MANAGER, DIRECTOR}; void print (); emp_type type() { return _type; } // … private: emp_type _type; }; 並在三個類別的建構函式中,加入資料成員 type 的設定。經過這些加工之後,你就可以寫出下一頁的列印函式。 void print_emp (Employee *e) { switch (e-type()) { case Employee::EMPLOYEE: e-print(); break; case Employee::MANAGER: static_castManager *(e)-print(); // Manager’s print() break; case Employee::DIRECTOR: static_castDirector *(e)-print(); // Director’s print() break; } } 上述的解決方案有下面兩個缺點: 就如同 print_emp() 函式所示,程式設計師必須判斷物件的類別,然後採取適當的型態轉換。這種作法不僅增加程式撰寫的負擔,也容易造成錯誤。 print_emp() 函式只能列印 Employee、Manager、和 Director 三種類別的物件。如果其他人用繼承的方式定義另一種員工的類別,如 Secretary,則已經寫死的 print_emp() 函式將無法用來列印這個新類別的物件。 class Secretary : public Employee { public: void print (); // … }; 為了解決上述的問題,C++ 提供一種稱為 virtual 函式的特別成員函式。你只要在成員函式的宣告之前加上關鍵字 virtual,就可以把它變成 virtual 函式,即 virtual return_type func_nam

文档评论(0)

1亿VIP精品文档

相关文档