Object-Oriented Programming:

Slides:



Advertisements
Similar presentations
系統分析與設計 楊子青 H-1 H 、物件導向技術 n 物件導向的基本概念 – 物件、類別 – 封裝、繼承 – 同名異式 ( 多型 ) 、超荷 ( 過載 ) n 物件導向分析與設計及塑模工具 n UML 塑模工具.
Advertisements

Ch02物件導向程式設計 物件導向系統分析與設計.
第四章 继承与派生 Chapter 4 Inheritance and Derivation
Java Programming Hygiene - for DIDC
第一章 面向对象程序设计.
程設一.
類別與物件 Class & Object.
第15章 繼承與多重繼承 15-1 繼承的基礎 15-2 覆寫與隱藏父類別的成員 15-3 子類別的建構與解構子 15-4 多重繼承
Data Abstraction: The Walls
第八章 类和对象.
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
Chapter 1 用VC++撰寫程式 Text book: Ivor Horton.
H、物件導向技術 物件導向的基本概念 物件、類別 封裝、繼承 同名異式(多型) 、超荷(過載) 物件導向分析與設計及塑模工具 UML塑模工具.
物件導向程式設計 (Object-Oriented rogramming)
Chap 18 類別與物件 夫有土者,有大物也。有大物者,不可以物。 物而不物,故能物物。 明乎物物者之非物也,豈獨治天下百姓而已哉!
4.1 概述 4.2 类与对象的实现 4.3 对象的初始化和析构 4.4 类的包含 4.5 类模板
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
Classes Lecturer: 曾學文.
CHAPTER 9 建構方法 ROBERT.
Scope & Lifetime 前言 Local Scope Global Functions & Objects
第六章 类的扩展与继承.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
第16章 VB.NET物件導向與.NET Framework
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
Classes: A Deeper Look, Part 1
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
创建型设计模式.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
類別樣板 Class Template 類似函式樣板 由類別樣板產生的類別稱為類別樣版的實體(instance)
第3章 继承和派生.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Java软件设计基础 5. 继承与多态.
Object-Oriented Programming in C++ 第一章 C++的初步知识
第9章 類別圖與物件圖 9-1 類別圖與物件圖的基礎 9-2 類別圖的符號 9-3 類別關係 9-4 物件圖 9-5 繪製類別圖與物件圖
Java程序设计 第9章 继承和多态.
Object-Oriented Programming: Polymorphism
SPOTO TM JAVA课程 JAVA中的OO语法
第四章 小技巧.
第九單元 Classes and data abstraction I
面向对象程序设计 QQ群: Object-Oriented Programming 汽车学院.
类类型 C++支持的内置类型和操作,如 int i=10; i=i%6; i=i+4;
软件学院 张 慧 清华大学软件学院.
Php class 組員: 賴羿陵 林昱廷 莊正暉 張雅晴
第5讲 使用类和对象编程(三) 内部类 实例 程序控制结构 选择语句.
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
第7章 繼承/多型/介面 注意: 本投影片僅供本書上課教師使用,非經同意請勿上網轉載或供拷貝.
Classes (2) Lecture 7.
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
Speaker: Liu Yu-Jiun Date: 2009/4/29
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
Speaker: Liu Yu-Jiun Date: 2009/5/6
Inheritance -II.
第三章 数据抽象.
Object-Oriented Programming in C++ 第二章 类和对象
面向对象技术 练习 ffh.
第 9 章 建構函式與解構函式.
#include <iostream.h>
第 5 章 继承、多态和虚函数 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
JAVA 程式設計與資料結構 第三章 物件的設計.
對於成員(member)存取權的限制 成員的資料被毫無限制的存取,任誰都可以指定任意值給成員,Java語言為了防止這種現象的產生,規定:有一種成員的資料不能任由類別外部的任何人隨意存取。
C++语言程序设计(第4版) 第七章 继承与派生 数学与统计科学学院 胡凤珠.
資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010.
Introduction to the C Programming Language
Presentation transcript:

Object-Oriented Programming: Chapter 12 Object-Oriented Programming: Inheritance

OBJECTIVES To create classes by inheriting from existing classes. How inheritance promotes software reuse. The notions of base classes and derived classes and the relationships between them. The protected member access specifier. The use of constructors and destructors in inheritance hierarchies. The differences between public, protected and private inheritance. The use of inheritance to customize existing software.

Topics 12.1 Introduction 12.2 Base Classes(基类) and Derived Classes (派生类) 12.3 protected Members 12.4 Relationship between Base Classes and Derived Classes 12.5 Constructors and Destructors in Derived Classes 12.6 public, protected and private Inheritance 12.7 Software Engineering with Inheritance

12.1 Introduction --继承的概念 重写? 重用? 软件重用 在已存在的类基础上构建新的类 Graduate Student 吸纳已有类的数据及行为(数据成员及成员函数) 可以强化扩展一些新的功能 Graduate Student String Name int Age ……. Void Exam() Void Research() Student String Name int Age ……. Void Exam() 重写? 重用?

12.1 Introduction --类之间的关系 public Shape 基 类 Is-a(继承) Has-a(组合) protected Inheritance (继承关系) private Circle 派生类 声明格式:class <派生类名>:<继承方式><基类名> {……}; class Circle: public Shape{……}; 图 形 开放图形 闭合图形 多边形 椭圆形 折线 直线 弧线

is-a和has-a的区别? is-a代表继承 has-a代表组合关系 一个类继承自另一个类 属于更加专有的一类对象 可以一个类继承一些行为,也可修改甚至创建新的行为 例如vehicle类,有加速、减速等行为,car继承vehicle,同样有这些行为,也可以有新的行为(如打开后备箱等) has-a代表组合关系 一个对象包含其它的成员对象 例如Employee类中包含firstname、lastname、birthdate、hiredate等对象

Topics 12.1 Introduction 12.2 Base Classes(基类) and Derived Classes (派生类) 12.3 protected Members 12.4 Relationship between Base Classes and Derived Classes 12.5 Constructors and Destructors in Derived Classes 12.6 public, protected and private Inheritance 12.7 Software Engineering with Inheritance

12.2 Base Classes and Derived Classes Class GraduateStudent: public Student{……}; ……

12.2 Base Classes and Derived Classes 继承的层次关系(大学社区成员关系图示例) 继承机制作用: 软件复用;对事物进行分类; 支持软件的增量开发;对概念进行组合。

12.2 Base Classes and Derived Classes 定义派生类时需指出继承方式,如未显式指出,默认为private 单继承:class TwoDimensionalShape : public Shape 多继承:class AdministratorTeacher: public Teacher, public Administrator tetrahedron [5tetrE5hedrEn] n. [数][晶]四面体 tet.ra.he.dron AHD:[tµt”r…-h¶“dr…n] D.J.[7tetr*6hi8dr*n] K.K.[7tWtr*6hidr*n] n.(名词) 【复数】 tet.ra.he.drons或 tet.ra.he.dra [-dr…] A polyhedron with four faces. 四面体:有四个面的多面体

访问规则 派生类吸纳基类的数据成员及成员函数(隐性) 派生类的成员函数如何访问基类的数据成员和成员函数?(public继承)

void setAX( int a) { x = a ; } void setAX( int a) { setX(a) ; } class One{ public: void setX (int a) {x = a;} void print() {cout << x;} private: int x; }; class Two: public One{ void outputX() {print();} Int mian() { Two two; two. outputX(); two.setAX(5); } OK Error void setAX( int a) { x = a ; } void setAX( int a) { setX(a) ; }

访问规则 派生类的成员函数如何访问基类的数据成员和成员函数?(public继承) 可以访问基类中的非private数据成员及成员函数 无法直接访问基类的private成员 可以通过基类中提供的非private成员函数实现对基类中private数据成员进行修改 通常派生类需要重新定义一些成员函数,以实现派生类特有的功能及操作

Topics 12.1 Introduction 12.2 Base Classes and Derived Classes 12.3 Protected Members 12.4 Relationship between Base Classes and Derived Classes 12.5 Constructors and Destructors in Derived Classes 12.6 public, protected and private Inheritance 12.7 Software Engineering with Inheritance

12.3 Protected Members 需求: 类有两种用户:类实例和派生类 如何使派生类可以访问基类的成员,同时又能够使基类的成员不被类的实例用户访问? 基类的protected成员可以被派生类的成员和友元访问 class A { private: int x,y; }; class B: public A { void printXY() {cout<<x<<y;} int main() { A a; a.x=9; return 0; } public protected error C2248: cannot access private member declared in class 'A'

继承中的访问模式(public继承) 基类的public成员能够被程序中所有函数访问 基类的private成员只能被基类的成员函数和友元访问 基类的protected成员只能被基类的成员和友元以及派生类的成员和友元访问。 注意:不能被类的实例(对象)访问。 派生类如何访问基类的数据成员? 默认情况:派生类成员简单地使用成员名就可以引用基类的public成员和protected成员。 当派生类重新定义了基类的成员函数时,访问方式: base-class name:: + 成员函数

error C2660: 'f' : function does not take 0 parameters class A { private: int x,y; public: void f(); void g() const {cout<<x<<‘,’<<y<<endl; } }; class B: public A { int z; void h() { f(); A::f(); } int main() { B b; b.f(); b.A::f(); b.h(); return 0; } error C2660: 'f' : function does not take 0 parameters void f(int); void h(); { f(1); 只要在派生类中重写基类的函数(函数名相同,即使参数不同),就无法默认调用基类的相关函数,此时基类中的函数需要“基类::函数名”来调用。

Topics 12.1 Introduction 12.2 Base Classes and Derived Classes 12.3 Protected Members 12.4 Relationship between Base Classes and Derived Classes 12.5 Constructors and Destructors in Derived Classes 12.6 public, protected and private Inheritance 12.7 Software Engineering with Inheritance

12.4 Relationship between Base Classes and Derived Classes 12.4.1 Creating and Using a CommissionEmployee Class 12.4.2 Creating a BasePlusCommissionEmployee Class Without Using Inheritance 12.4.3 Creating a CommissionEmployee-BasePlusCommissionEmployee Inheritance Hierarchy 12.4.4 CommissionEmployee-BasePlusCommissionEmployee Inheritance Hierarchy Using protected Data 12.4.5 CommissionEmployee-BasePlusCommissionEmployee Inheritance Hierarchy Using private Data

12.4.1 Creating and Using a CommissionEmployee Class Create class CommissionEmployee, which contains as private data members a first name, last name, social security number, commissionrate (percentage) and gross (i.e., total) sales amount. P 12.4 - 6 程序解读

#include <string> using std::string; class CommissionEmployee { public: CommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0 ); void setFirstName( const string & ); string getFirstName() const; // return first name void setLastName( const string & ); string getLastName() const; void setSocialSecurityNumber( const string & ); string getSocialSecurityNumber() const; void setGrossSales( double ); double getGrossSales() const; void setCommissionRate( double ); // set commission rate (percentage) double getCommissionRate() const; // return commission rate double earnings() const; // calculate earnings void print() const; // print CommissionEmployee object private: string firstName; string lastName; string socialSecurityNumber; double grossSales; // gross weekly sales double commissionRate; // commission percentage }; // end class CommissionEmployee

2018年11月30日9时38分 12.4.2 Creating a BasePlusCommissionEmployee Class Without Using Inheritance Define class BasePlusCommissionEmployee, which contains as private data members a first name, last name, social security number, commission rate, gross sales amount and base salary. We create the latter class by writing every line of code the class requires we will soon see that it is much more efficient to create this class simply by inheriting from class CommissionEmployee. P 12.4 - 9 程序解读

注意:从一个类向另一个类复制粘贴代码,可能造成错误在多个源代码文件中扩散! class BasePlusCommissionEmployee { public: BasePlusCommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0 ); void setFirstName( const string & ); // set first name string getFirstName() const; // return first name void setLastName( const string & ); // set last name string getLastName() const; // return last name void setSocialSecurityNumber( const string & ); // set SSN string getSocialSecurityNumber() const; // return SSN void setGrossSales( double ); // set gross sales amount double getGrossSales() const; // return gross sales amount void setCommissionRate( double ); // set commission rate double getCommissionRate() const; // return commission rate void setBaseSalary( double ); // set base salary double getBaseSalary() const; // return base salary double earnings() const; // calculate earnings void print() const; // print BasePlusCommissionEmployee object private: string firstName; string lastName; string socialSecurityNumber; double grossSales; // gross weekly sales double commissionRate; // commission percentage double baseSalary; // base salary }; // end class BasePlusCommissionEmployee 注意:从一个类向另一个类复制粘贴代码,可能造成错误在多个源代码文件中扩散!

BasePlusCommissionEmployee 12.4.3 Creating a CommissionEmployee-BasePlusCommissionEmployee Inheritance Hierarchy (派生类中不能直接访问基类的私有成员) BasePlusCommissionEmployee class that inherits directly from class CommissionEmployee 基类 CommissionEmployee i.e., a BasePlusCommissionEmployee is a CommissionEmployee who also has a base salary) and attempts to access class CommissionEmployee's private members, this results in compilation errors, because the derived class does not have access to the base class's private data 继承 BasePlusCommissionEmployee 派生类

程序解读 P 12.10 -12 #include <string> // C++ standard string class using std::string; #include "CommissionEmployee.h“ class BasePlusCommissionEmployee : public CommissionEmployee { public: BasePlusCommissionEmployee( const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0 ); void setBaseSalary( double ); double getBaseSalary() const; double earnings() const; // calculate earnings void print() const; private: double baseSalary; }; P 12.10 -12 程序解读

关于初始化问题——review 如何进行初始化? 构造函数和析构函数不能继承 在创建子类对象时,为了初始化从父类继承来的数据成员,系统需要调用其父类的构造函数 所有的类成员都可以用构造函数初始化列表进行初始化,而以下情况只能如此: const data member (例外?const static integer/char) reference data member 引用类型的数据成员 member objects, 数据成员是其他类(未提供缺省构造函数)的对象 继承类(利用基类的构造函数)

BasePlusCommissionEmployee::BasePlusCommissionEmployee( const string &first, const string &last, const string &ssn, double sales, double rate, double salary ) : CommissionEmployee( first, last, ssn, sales, rate ) { setBaseSalary( salary ); // validate and store base salary } double BasePlusCommissionEmployee::earnings() const return baseSalary + ( commissionRate * grossSales ); //Error 派生类的成员函数无法访问基类的private成员

注意: 如果派生类的构造函数没有显示调用基类的构造函数,C++将尝试隐式调用默认的构造函数(前提:基类需要有缺省的构造函数) 采用成员初始化器列表显示地初始化成员对象和调用基类的构造函数,可以防止重复初始化

注意: 在派生类头文件中使用#include包含基类头文件 连接过程 告诉编译器基类的存在 让编译器根据类的定义确定对象的大小,派生类的对象大小取决于派生类显式定义的数据成员和继承自基类的数据成员 让编译器能够判断派生类是否正确的使用了基类的成员 连接过程 C++ Standard Library classes CommissionEmployee .obj BasePlusCommissionEmployee .obj client. obj Linker exe code

12.4.4 CommissionEmployee-BasePlusCommissionEmployee Inheritance Hierarchy Using protected Data(使用protected成员) if CommissionEmployee's data is declared as protected, a new version of class BasePlusCommissionEmployee that inherits from class CommissionEmployee can access that data directly. Both the inherited and noninherited BasePlusCommissionEmployee classes contain identical functionality, but we show how the version of BasePlusCommissionEmployee that inherits from class CommissionEmployee is easier to create and manage. P 12.12 -16 程序解读

Notes on protected data (注意事项) 影响数据的有效性检查 派生类可以直接访问基类的protected数据成员 派生类依赖于基类的实现 基类的数据成员发生改变有可能影响派生类的实现 软件“易碎”或“脆弱”,不够健壮 基类仅向派生类提供服务,则可使用protected类型声明,其他情况慎用protected

12.4.5 CommissionEmployee-BasePlusCommissionEmployee Inheritance Hierarchy Using private Data(在派生类中重定义基类成员) Set the CommissionEmployee data members back to private to enforce good software engineering. use base class CommissionEmployee's public member functions to manipulate CommissionEmployee's private data. P 12.17 -20 程序解读

注意: 通过调用基类的public成员函数来访问基类的私有数据成员 当功能相同时,尽量调用成员函数,以避免代码拷贝。 重定义基类成员函数时,一定要使用“::”访问基类成员,否则会引起无限递归,例如:earnings() 注意print()和earnings()的重新定义:调用基类的print()和earnings()函数 符合软件工程要求:使用继承,通过调用成员函数隐藏了数据,保证了数据的一致性。

Topics 12.1 Introduction 12.2 Base Classes and Derived Classes 12.3 Protected Members 12.4 Relationship between Base Classes and Derived Classes 12.5 Constructors and Destructors in Derived Classes 12.6 public, protected and private Inheritance 12.7 Software Engineering with Inheritance

12.5 Constructors and Destructors in Derived Classes 构造顺序 建立派生类的实例对象时、必须调用基类的构造函数来初始化派生类对象的继承成员。 派生类的构造函数既可以隐式调用基类的构造函数,也可以在派生类的构造函数中通过给基类提供初始化值显式地调用。 基类构造函数->派生类构造函数 析构顺序 析构函数的调用顺序和构造函数的顺序相反,因此派生类的析构函数在基类析构函数之前调用。 P 12.22-26 程序解读

Review 全局对象:在任何函数(含main)执行前,构造;在程序结束时,析构. 局部对象: 自动变量:对象定义时,构造;块结束时,析构. 静态变量:首次定义时,构造;程序结束时,析构. 对象析构顺序恰好与构造顺序相反. 特例1:调用exit函数退出程序执行时,不调用剩余自动对象的析构函数. 特例2:调用abort函数退出程序执行时,不调用任何剩余对象的析构函数.

BasePlueCommissionEmployee BasePlueCommissionEmployee int main() { cout << fixed << setprecision( 2 ); { // begin new scope CommissionEmployee employee1( "Bob", "Lewis", "333-33-3333", 5000, .04 ); } // end scope cout << endl; BasePlusCommissionEmployee employee2( "Lisa", "Jones", "555-55-5555", 2000, .06, 800 ); employee3( "Mark", "Sands", "888-88-8888", 8000, .15, 2000 ); return 0; } // end main CommissionEmployee constructor: CommissionEmployee destructor: BasePlueCommissionEmployee constructor: BasePlueCommissionEmployee destructor: CommissionEmployee denstructor: employee3 BasePlueCommissionEmployee CommissionEmployee employee2 BasePlueCommissionEmployee CommissionEmployee Block employee1

12.5 Constructors and Destructors in Derived Classes -- 包含成员对象 假设基类和派生类都包含其他类的对象: 在建立派生类的对象时,首先执行基类成员对象的构造函数,接着执行基类的构造函数,然后执行派生类的成员对象的构造函数,最后才执行派生类的构造函数。析构函数的调用次序与调用构造函数的次序相反。 基类成员对象初始化—>基类的构造函数—>派生类成员对象初始化—>派生类构造函数 建立成员对象的顺序是对象在类定义中的声明顺序。成员初始化器中的顺序不影响建立对象的顺序。 对继承关系,基类构造函数的调用顺序是派生类定义中指定的继承顺序,派生类成员初始化值列表中指定的基类构造函数的顺序不影响对象的建立顺序。

Class1 default constructor! BaseClass default constructor! class Class1{ public: Class1(int a) { cout<<"Class1 constructor!"<<endl; num = a; } Class1() { cout<<"Class1 default constructor!"<<endl; } ~Class1() {cout<<"Class1 deconstructor!"<<endl;} private: int num; }; class BaseClass{ BaseClass(int a, int b): t(a) { cout<<"BaseClass constructor!"<<endl; num = b; }; BaseClass() {cout<<"BaseClass default constructor!"<<endl;} ~BaseClass() {cout<<"BaseClass deconstructor!"<<endl;} private: Class1 t; int num; }; class DerivingClass:public BaseClass{ public: DerivingClass(int a, int b): t1(a) ,BaseClass(a,b) {cout<<"DerivingClass constructor!"<<endl; num = b; }; ~DerivingClass() {cout<<"DerivingClass deconstructor!"<<endl;} private: Class1 t1; int num; }; int main() { DerivingClass obj(10, 20); return 0; } Class1 default constructor! BaseClass default constructor! Class1 constructor! DerivingClass constructor! DerivingClass deconstructor! Class1 deconstructor! BaseClass deconstructor!

Topics 12.1 Introduction 12.2 Base Classes and Derived Classes 12.3 Protected Members 12.4 Relationship between Base Classes and Derived Classes 12.5 Constructors and Destructors in Derived Classes 12.6 public, protected and private Inheritance 12.7 Software Engineering with Inheritance

12.6 public, protected and private Inheritance 2018年11月30日9时38分 继承方式 基 类 派生类 public public成员 protected成员 private成员 不可直接使用 private protected (很少使用) 注意:友元函数是不被继承的

进一步阐述——公有继承 (1) 基类成员对其对象的可见性: (2) 基类成员对派生类的可见性: (3) 基类成员对派生类对象的可见性: 公有成员可见,其他不可见。这里保护成员同于私有成员。 (2) 基类成员对派生类的可见性: 公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。 (3) 基类成员对派生类对象的可见性: 公有成员可见,其他成员不可见。(见前表) 一定要区分派生类的对象和派生类中的成员函数对基类的访问是不同的。

进一步阐述——私有继承 (1) 基类成员对其对象的可见性: (2) 基类成员对派生类的可见性: (3) 基类成员对派生类对象的可见性: 公有成员可见,其他成员不可见。(同前) (2) 基类成员对派生类的可见性: 公有成员和保护成员可见,私有成员不可见。(同前) (3) 基类成员对派生类对象的可见性: 所有成员都不可见。(见前表) 保护继承与私有继承类似

总结 不论公有继承还是私有继承,基类成员对于派生类的访问权限是不变的。(可访问公有或保护类型成员) 变化的是派生类的对象以及派生类的派生类对基类成员的访问权限。

Topics 12.1 Introduction 12.2 Base Classes and Derived Classes 12.3 Protected Members 12.4 Relationship between Base Classes and Derived Classes 12.5 Constructors and Destructors in Derived Classes 12.6 public, protected and private Inheritance 12.7 Software Engineering with Inheritance

12.7 Software Engineering with Inheritance 派生类的程序员不需了解基类的源代码,只需与目标代码连接即可 ISV(Independent software vendors 独立的软件供应商)为目标代码提供头文件,发放许可 继承实用的类库,提高软件复用 软件工程提示: 提取出共同的属性和行为并把它们放在一个基类中,然后,再通过继承生成派生类。 尽量建立较少的类,避免不必要的类

Summary 基类和派生类的定义 Protected成员 基类和派生类的关系:public,proteced,private 继承关系中构造函数和析构函数顺序 复合(has-a)和继承(is-a)的关系 “使用”和”知道”

Homework! 上机题目 12.10