继承/派生一 类的继承/派生 什么是类的继承/派生 ■ 怎么定义派生类 ■如何继承父类的成员 ■ 派生类的构造函数和析构函数 ■ 类型兼容规则:派生类对象/父类对象 多重继承时重复继承问题一虚父类 http://math.ecnu.edu.cn/~jypan 2
http://math.ecnu.edu.cn/~jypan 2 继承/派生 —— 类的继承/派生 什么是类的继承/派生 怎么定义派生类 如何继承父类的成员 派生类的构造函数和析构函数 类型兼容规则:派生类对象/父类对象 多重继承时重复继承问题 — 虚父类
什么是继承/派生 什么是继承/派生: 在已有的类的基础上定义新的类→类的派生 为什么继承/派生: 一一继承可以使得派生类具有父类的各种属性和功能, 而不需要再次编写相同的代码。 十派生类在继承父类的同时,还可以通过重新定义某些属性或改写某些方法,来更 新父类的原有属性和功能,或增加新的属性和功能。 http://math.ecnu.edu.cn/~jypan 3
http://math.ecnu.edu.cn/~jypan 什么是继承/派生 什么是继承/派生: —— 在已有的类的基础上定义新的类 类的派生 为什么继承/派生: —— 继承可以使得派生类具有父类的各种属性和功能, 而不需要再次编写相同的代码。 † 派生类在继承父类的同时,还可以通过重新定义某些属性或改写某些方法,来更 新父类的原有属性和功能,或增加新的属性和功能。 3
什么是继承/派生(续) ●在已有类的基础上产生新类的过程就是类的派生 ·原有类称为父类或基类,新类称为子类或派生类 ●类的继承:派生类继承了父类的特性(数据和函数) 。派生类可以加入新的特性 ·派生类也可以作为父类,派生新的子类→继承层次结构 火车 大卡车 例: 交通工具 汽车 小轿车 飞机 面包车 十继承和派生提高了代码的可重用性,有利于软件开发和维护。 4 http://math.ecnu.edu.cn/~jypan
http://math.ecnu.edu.cn/~jypan 什么是继承/派生(续) 在已有类的基础上产生新类的过程就是类的派生 原有类称为父类或基类,新类称为子类或派生类 类的继承:派生类继承了父类的特性(数据和函数) 派生类可以加入新的特性 派生类也可以作为父类,派生新的子类 继承层次结构 例: 交通工具 火车 汽车 飞机 大卡车 小轿车 面包车 † 继承和派生提高了代码的可重用性,有利于软件开发和维护。 4
怎么定义派生类 c1ass派生类名:继承方式父类名1,继承方式父类名2,. 派生类成员声明; ,一个派生类可以有多个父类(多重继承) ●单继承:一个派生类只有一个父类 )一个父类可以派生出多个子类→类族 继承是可传递的:从父类继承的特性可以传递给新的子类 继承方式:规定了如何访问从父类继承的成员 继承方式有三种:public、protected、private 派生类成员:从父类继承的成员+新增加的成员 http://math.ecnu.edu.cn/~jypan 5
http://math.ecnu.edu.cn/~jypan 怎么定义派生类 class 派生类名: 继承方式 父类名1, 继承方式 父类名2, ... { 派生类成员声明; }; 一个派生类可以有多个父类(多重继承) 单继承:一个派生类只有一个父类 一个父类可以派生出多个子类 类族 ► 继承是可传递的:从父类继承的特性可以传递给新的子类 ► 继承方式:规定了如何访问从父类继承的成员 ► 继承方式有三种:public、protected、private ► 派生类成员:从父类继承的成员+新增加的成员 5
类的派生过程 派生过程:吸收父类成员,改造父类成员,添加新成员。 ●吸收父类成员 派生类包含父类中除构造和析构函数外的所有非静态成员 ·改造父类成员 -父类成员的访问控制(通过继承方式实现) 一对父类成员的覆盖或屏蔽,即如果新成员与父类成员同名,则只能访问 新成员(包括函数,即使形参不一致,也被屏蔽) ●添加新成员 根据实际需要,添加新的数据成员或函数成员 十注意:构造函数、析构函数、静态成员不能被继承! http://math.ecnu.edu.cn/~jypan 6
http://math.ecnu.edu.cn/~jypan 类的派生过程 派生过程:吸收父类成员,改造父类成员,添加新成员。 吸收父类成员 派生类包含父类中除构造和析构函数外的所有非静态成员 改造父类成员 - 父类成员的访问控制(通过继承方式实现) - 对父类成员的覆盖或屏蔽,即如果新成员与父类成员同名,则只能访问 新成员(包括函数,即使形参不一致,也被屏蔽) 添加新成员 根据实际需要,添加新的数据成员或函数成员 † 注意:构造函数、析构函数、静态成员不能被继承! 6
派生类成员的访问控制 访问控制:能否访问/怎样访问从父类继承得来的成员。 ·主要指派生类中新增成员和派生类外部函数访问派生类从父类继承的成员 继承方式不同,访问控制不同 公有继承(public) ·父类的公有和保护成员的访问属性保持不变 ·父类的私有成员不可直接访问 从父类继承的成员函数对父类成员的访问不受影响! http://math.ecnu.edu.cn/~jypan 7
http://math.ecnu.edu.cn/~jypan 派生类成员的访问控制 访问控制:能否访问/怎样访问从父类继承得来的成员。 ► 主要指派生类中新增成员和派生类外部函数访问派生类从父类继承的成员 继承方式不同,访问控制不同 † 从父类继承的成员函数对父类成员的访问不受影响! ► 父类的公有和保护成员的访问属性保持不变 ► 父类的私有成员不可直接访问 公有继承(public) 7
例:公有继承 Example class Point public: void initPoint(float x=0,float y=0); void move(float offx,float offy); float getx()const {return x;} float gety()const {return y;} private: f1oat×,y; Example class Rectangle:public Point { public: void initRect(float x,float y,float w,float h) initPoint(x,y);this->w=w;this->h=h; float geth()const {return h;} float getw()const {return w;} private: f1oath,w;/新增私有成员 http://math.ecnu.edu.cn/~jypan 8
http://math.ecnu.edu.cn/~jypan 例:公有继承 class Point { public: void initPoint(float x=0, float y=0); void move(float offx, float offy); float getx() const {return x;} float gety() const {return y;} private: float x, y; } class Rectangle: public Point { public: void initRect(float x,float y,float w,float h) { initPoint(x,y); this->w=w; this->h=h; } float geth() const {return h;} float getw() const {return w;} private: float h, w; // 新增私有成员 } Example Example 8
派生类成员的访问控制(续) 私有继承(private) ·父类的公有和保护成员都成为派生类的私有成员 ·父类的私有成员不可直接访问 保护继承(protected) ·父类的公有和保护成员都成为派生类的保护成员 ·父类的私有成员不可直接访问 十与私有继承的区别: 父类成员(特别是公有函数)可以在以后的派生中作为保护成员继承下去。 十私有继承后,父类成员(特别是公有函数)无法在以后的派生类中直接发挥作用, 相当于终止了父类功能的继续派生。因此,私有继承较少使用。 http://math.ecnu.edu.cn/~jypan
http://math.ecnu.edu.cn/~jypan 9 派生类成员的访问控制(续) † 私有继承后,父类成员(特别是公有函数)无法在以后的派生类中直接发挥作用, 相当于终止了父类功能的继续派生。因此,私有继承较少使用。 † 与私有继承的区别: 父类成员(特别是公有函数)可以在以后的派生中作为保护成员继承下去。 ► 父类的公有和保护成员都成为派生类的私有成员 ► 父类的私有成员不可直接访问 私有继承(private) ► 父类的公有和保护成员都成为派生类的保护成员 ► 父类的私有成员不可直接访问 保护继承(protected)
访问控制小结 ●父类成员函数访问父类成员:正常访问 ●派生类成员函数访问派生类新增成员:正常访问 ●父类成员函数访问派生类新增成员:不能访问 ●派生类成员函数访问父类成员:继承方式+成员本身访问属性 ●非成员函数访问派生类所有成员:只能访问公有成员 ·派生类成员按访问属性可划分为下面四类: -不可访问成员:父类的私有成员 -私有成员:父类继承的部分成员+新增的私有成员 -保护成员:父类继承的部分成员+新增的保护成员 -公有成员:父类继承的部分成员+新增的公有成员 如果没有指定继承方式,则缺省为private http://math.ecnu.edu.cn/~jypan 10
http://math.ecnu.edu.cn/~jypan 10 访问控制小结 父类成员函数访问父类成员:正常访问 派生类成员函数访问派生类新增成员:正常访问 父类成员函数访问派生类新增成员:不能访问 派生类成员函数访问父类成员:继承方式+成员本身访问属性 非成员函数访问派生类所有成员:只能访问公有成员 派生类成员按访问属性可划分为下面四类: - 不可访问成员:父类的私有成员 - 私有成员:父类继承的部分成员 + 新增的私有成员 - 保护成员:父类继承的部分成员 + 新增的保护成员 - 公有成员:父类继承的部分成员 + 新增的公有成员 † 如果没有指定继承方式,则缺省为 private
派生类访问控制:例一 class Person /川父类 public: Person(string str,int age )name(str) this->age age; void show() { cout <"Name:"<name <endl; cout <<"Age:"<<age<<endl; private: string name; /1姓名 int age; //年龄 } http://math.ecnu.edu.cn/~jypan 11
http://math.ecnu.edu.cn/~jypan 11 派生类访问控制:例一 class Person // 父类 { public: Person(string & str, int age ) : name(str) { this->age = age; } void show() { cout << "Name: " << name << endl; cout << "Age: " << age << endl; } private: string name; // 姓名 int age; // 年龄 };