第04章 类的继承与派生
继承与派生
4.1 继承和派生的概念
在软件开发过程中,在定义特殊类时,不需把它的一 般类已经定义过的属性和服务重复地书写一遍,只需要声 明它是某个类的特殊类,并定义它自己的特殊属性和服务。 这将明显地减轻开发工作的强度。 4.1.2 继承的作用 面向对象程序设计的继承性使得大型应用程序的维护 和设计变得更加简单。一方面,大型应用程序设计完成并 交付使用后,经常面临用户的需求发生变化,程序功能需 要扩充等问题。这时程序的修改需要非常谨慎,因为某个 局部的修改可能会影响其他部分,而一个正在使用中的系 统要进行全面的测试,既费时间又有很多实际的困难。另 一方面,一个新的应用系统程序设计在许多方面会和以前 设计过的某个或某些系统的模块非常类似,怎样加快大型 应用程序的开发速度,重用这些已经开发成功的程序模块, 一直是软件设计中迫切需要解决的问题。
4.2 派生类
C++语言派生类多重继承的定义格式如下: class <派生类名>:[继承方式1] [<基类名1>],[继承 方式2] [<基类名2>],…, [继承方式n] [<基类名n>] { <派生类成员变量和成员函数定义> }; 通常,在多重继承时,继承方式设计成一致的形式。 如继承方式均设计成public,或均设计成private。
面向对象的程序设计:四、 类的继承与派生
11
派生类的定义
派生类构造函数及析构函数的构造规则
• 当基类构造函数没有参数,或没有显式定义构 造函数时,派生类可以不向基类传递参数,甚 至可以不定义构造函数。 • 若基类使用缺省或不带参数的构造函数,则在 派生类定义构造函数是可略去“基类构造函数 名(参数表)”,此时若派生类也不需要构造 函数,则可不定义构造函数。
Employee
由共性到个性
Transportation
Teacher
Officer
Worker
Flight
Vehicle
Ship
Car
Байду номын сангаас
Truck
Van
一般到特殊
基类
派生类
3
派生类的定义
派生类可以分为共有(public)派生类、私有(private) 派生类和保护(protected)派生类,其一般定义为:
18
多重继承
多继承中的二义性
• 如果多个基类中具有相同名字的成员,则派生类在引 用时就具有二义性。例如: class A{ public: void f();}; class B{ public: void f(); void g();}; class C: public A, public B { public: void g(); void h();}; main() { C a; a.f(); a.g();//二义性 }
运行结果 constructing base constructing derive destructing derive destructing base
13
派生类的定义
派生类构造函数及析构函数的构造规则
• 当基类的构造函数带有参数时,所有的派 生类都必须定义构造函数。有时所定义 的派生类的构造函数的函数体可以为空, 仅仅起参数传递作用。
C++类的继承和派生
单击此处添加副标题
演讲人姓名
单击此处添加正文,文字是您思想的提炼,为了演示发布的良好效果,请言简意赅地阐述您的观点。
1
面向对象程序设计有4个主要特点: 抽象、封装、继承和多态性。在本章中主要介绍有关继承的知识,在下一章中将介绍多态性。 C++语言提供了类的继承机制,解决了软件重用问题。
如果在派生类中定义了和基类中同名函数(函数参数个数和类型可以相同也可以不相同),则派生类中的函数会隐藏基类的同名函数。在派生类中不能直接访问基类中的同名函数。(注意与重载的区别。在同一个类中的同名不同参函数为重载函数)
如程序PointRect1所示:
1
2
4.4继承方式
派生类的继承方式有三种:public,private,protected。不同的继承方式决定了基类成员在派生类中的访问属性。
void main(式
4.4.1 简单的派生类的构造函数
#include <iostream> #include<string> using namespace std; class Student { public: Student(int n,string nam,char s) {num=n; name=nam; sex=s; } ~Student( ){ } protected: int num; string name; char sex ; };
//Rectangle.h #include <iostream> #include "Point.h" using namespace std; class Rectangle:public Point { private: int width; int height; public: int GetWidth() { return width; } int GetHight() { return height; }
C _4_继承和派生
第四章继承和派生§4—1 继承§4—2 单继承§4—3多继承§4—1 继承一、继承的含义①面向对象方法提供了从问题域到解域的自然映射客观世界中的对象既有共性,也有个性,通过不同程度的抽象,形成了分类和层次结构不同层次的类之间体现了概括(generalize)和特化(specify)关系把高层次的类称为父类、超类和基类,把由该类特化产生的低层次类称为子类或派生类派生类不仅具有基类的属性和行为,还具有自己特有的属性和行为②在不同类之间,除了概括和特化的关系外,还有聚合和分解关系模块化的主要目的是实现软件的可复用性从模块的角度看,继承是一种关键性的复用技术③继承机制提供了一种充分利用现有资源的方法它既体现了经济思想,又体现了谦虚精神:我比别人看得远,是因我站在巨人的肩上——牛顿继承使得在创建新类时,只需说明新类与基类的区别,从而大量原有代码都可复用④派生类是基类的具体化,是基类定义的延续在多继承时,派生类也是基类的组合二、继承的概念1.基类即父类,超类,是已存在的用来派生新类的类,是被继承的类2.派生类即子类,是由己存在的类派生出的新类,是继承其他类特性的类3.单继承即单重继承,每个派生类只有一个直接父类是从一个基类派生的继承,形成类的层次,像一棵树4.多继承即多重继承,派生类可以有多个直接父类是从多个基类派生的继承,形成一个有向无环图(DAG图)5.类的层次结构直接基类、间接基类、直接派生类、间接派生类多层继承:一个基类可以是另一个基类的派生类区别:多层继承和多重继承三、派生类的定义①单继承class 派生类名: 继承方式基类名{派生类新定义成员;};②多继承class 派生类名: 继承方式1 基类名1,继承方式2 基类名2,……{派生类新定义成员;};四、继承方式共有三种:公有继承:public保护继承:protected私有继承:private 可缺省继承方式基类特性派生类特性公有继承public publicprotectedprivatepublicprotected不可访问或不可见保护继承public protectedprotected protectedprivate protected 不可访问私有继承(缺省)private publicprotectedprivateprivateprivate不可访问派生类不能继承基类的构造函数、析构函数和友元1.基类的私有成员只能被基类中的成员函数和友元函数访问,不能被其他函数访问2.基类的保护成员只能被基类及其派生类中的成员函数和友元函数访问3.公有继承派生类的对象可以访问基类中的公有成员派生类的成员函数可以访问基类中的公有成员和保护成员4.保护继承和私有继承派生类的对象不能访问基类中的任何成员派生类的成员函数可以访问基类中的公有和保护成员5.私有继承基类的公有和保护成员只能由直接派生类访问,无法再往下继承§4—2 单继承每个派生类只有一个直接基类,但每个基类可以有多个派生类一、成员访问权限的控制二、成员访问权限的调整①保护继承和私有继承将改变基类的公有和保护成员在派生类中的访问权限属性,若欲恢复其访问权限,则应作调整②方法:在派生类相应访问权限段中加以说明:基类名:: 成员名;③访问声明只能对变量或函数名,不能说明类型和参数④基类成员被调整后,在派生类中的访问权限既不能扩大也不能减小,即不能改变所属权限段⑤私有成员的访问权限不可调整,不能对私有段成员作访问声明⑥重载函数只需一个声明即可,具有不同访问权限的重载函数名不能作访问声明三、派生类的成员(1)由两部分组成:①派生类从基类继承来的成员,其封装体叫基类子对象(匿名对象)②派生类自定义成员(2)派生类对象的内存长度是基类数据成员和派生类自定义数据成员的内存空间之和(3)基类的私有成员在派生类中存在,但不可访问,不可见(4)静态成员受访问权限符的限制,但不受继承方式的制约派生类可用“基类名:: 静态成员名”访问基类的static成员(5)派生类共有四种成员:①公有成员②保护成员③私有成员④不可直接访问的成员,它由基类私有成员派生而来的(6)派生类直接访问基类私有成员的方法:①将基类私有段成员放于基类保护段②将派生类或派生类的成员函数声明为基类的友元四、改造基类成员(1)通过继承方式来控制基类成员在派生类中的访问权限(2)对基类成员进行同名覆盖①在派生类中声明一个与基类成员同名的新成员以屏蔽(隐藏)基类同名成员②在派生类中或通过派生类对象只能访问到派生类中新定义的同名成员③若在派生类中欲调用被编译器隐蔽起来的基类同名成员,则应作访问声明,明确指定基类类范围:对象名.基类名:: 成员名对象名.基类名:: 成员函数名(参数表)④同名覆盖时要求派生类与基类同名的新成员函数原型相同,数据成员的名字和类型相同当同名的基类成员函数和派生类成员函数的参数个数、类型和顺序不完全相同时,则属于函数重载⑤当欲对从基类继承过来的某些函数功能进行扩充和改造时,都可用同名覆盖原则来实现五、派生类的构造函数(1)派生类对象的数据结构,由基类数据成员和派生类自定义数据成员共同构成(2)构造函数不能被继承,基类子对象只能通过基类构函来初始化,常以成员初始化列表方式进行(3)定义:派生类名(总参数表):基类名(参数表),子对象名(参数表2),……{派生类自定义数据成员的初始化;}(4)派生类构造函数的调用执行顺序:①基类构造函数:先兄长②子对象类的构函:后客人③派生类构函:最后自己(5)当基类有无参数或缺省构函或未显式定义任何构函时,派生类构函中可省去对基类构函的调用(6)当基类构函有参数时,则派生类必须定义构函,以提供参数传递的途径(7)当派生类的基类也是一个派生类时,则每个派生类只需负责其直接基类构函的调用六、派生类的析构函数(1)析构函数不能被继承,基类子对象只能通过基类析构函数类释放(2)析构函数调用执行顺序与构函相反:①派生类析构函数:先自己②子对象类析构函数:再客人③基类析构函数:最后兄长七、赋值相容原理(1)即当派生类从基类公有继承时,派生类对象可自动隐式地转换一个基类对象(2)当公有继承时,在需要基类对象的任何地方,都可以使用公有派生类的对象来替代即公有派生类对象可以作为基类对象使用,但只能使用从基类继承来的成员(基类子对象)(3)公有派生类的对象、对象指针、对象引用都适用于基类对象、对象指针、对象引用所能使用的场合(4)赋值相容性不可逆若欲将基类对象指针转换成公有派生类对象指针,则必须显式进行类型转换不允许用基类对象给派生类对象赋值(5)也称为子类型对父类型的类型适应①子类型:对类型S,当且仅当它至少提供了类型T的行为,则称S是T的子类型②公有继承时,基类为父类型,派生类为子类型,派生类适应于基类③类型适应:若一个函数可用于父类型的对象,则它也可用于其各个子类型的对象(6)是多态性的基础,提高了编程效率八、多层继承(1)所有派生类都只需对其直接基类负责:派生类构函只需向其直接基类传递参数(2)可实现抽象机制和软件重用机制§4—3多继承一、多继承即多重继承①是单继承的扩展和组合,单继承可看作是多继承的特例②派生类有两个或两个以上的直接基类③派生类与每个基类之间仍可看作单继承④赋值相容性原理对多继承同样成立⑤同名覆盖规则对多继承仍成立⑥一个类不能多次被说明为同一个派生类的直接基类,即一个类不可以从同一个类中直接继承一次以上(可改用子对象方式)⑦可采用DAG图示法来表示各个基类与派生类的关系:箭头指向基类⑧一个类可以多次成为同一个派生类的间接基类二、多继承的构造函数与析构函数(1)定义:派生类名(总参数表):基类名1(参数表1),基类名2(参数表2),…,子对象名(参数表n),……{派生类构造函数体;}(2)派生类构函调用执行顺序:(与单继承相同)①先执行基类构函:先兄长②再执行子对象类构函:再客人③最后执行派生类本身的构函:最后自己(3)处于同一层次的各基类构函的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构函定义的成员初始化列表各项顺序无关(4)析构函数的调用执行顺序与构函相反三、多继承中的二义性问题(1)即派生类对基类成员访问的不唯一性(继承的模糊性)(2)调用不同基类的相同成员时可能出现二义性措施:使用作用域运算符,用类名对成员加以限定3)访问共同基类的成员时可能出现二义性措施:①用类名限定法来消除二义性,只能用派生类的直接类名来限定②在派生类中重定义一个与基类中同名的成员,以覆盖之③将公共基类说明为虚基类,使之在派生类中只有一个拷贝4)二义性检查是在访问控制和类型检查之前进行的,故只要不同基类有同名成员时,均会出现二义性,即使只有一个可被派生类访问或只有一个名字的类型符合要求(5)存在二义性,则编译时出错§4—4 虚基类1.即虚拟基类2.若类A是派生类C多条继承路径上的一个公共基类,则A在C的对象中将产生多个基类子对象若欲使其只有一个拷贝,则需将A设置为虚拟基类3.引入虚基类的目的:解决二义性问题,使派生类中只有公共基类的一个数据副本4.定义:class 派生类名:virtual 继承方式基类名5.虚基类子对象只被初始化一次,虚基类构函也只被执行一次6.若虚基类构函带有参数,则其直接或间接派生类的构函成员初始化列表中均应列出对虚基类构函的调用,但只有最后派生出来的用于声明对象的类对虚基类构函的调用才会被执行7.在同一层次中,虚基类构函先于非虚基类构函执行8.可节省内存空间,程序也更简洁9.一个类在作为某些类的虚基类的同时,还可以作为另一些派生类的非虚基类10.若虚基类由非虚基类派生而来,则先调用基类构函,再调用派生虚基类构函11.virtual常用于声明虚基类的直接派生类,可放于继承方式前,也可放于继承方式后面12.多继承时,virtual后紧跟的基类为虚基类,若有多个虚基类,则应用多个virtual来说明13.若同一层次中有多个虚基类,则其构函执行顺序取决于派生类定义时指定的顺序。
第04章 类的继承与派生
2019/2/12
4.3.2 析构函数
派生类的析构函数是在派生类对象生命期结 束之前对派生类新增的数据成员完成必要的 清理工作。
析构函数的作用与构造函数几乎正好相反,它在 对象删除前被自动调用,来完成一些清理工作, 也就是一些扫尾工作。 派生类析构函数执行顺序和构造函数刚好相反: 首先对派生类新增一般数据成员进行清理工作, 接着对派生类内嵌对象成员进行清理工作,最后 才是对基类继承的成员进行清理。这一点,大家 可以根据栈区“先进后出” 的特性来理解。
C++面向对象程序设计
2019/2/12
4.1.1 基类与派生类
以原有的类为基础产生新类,我们就说 从原有的类派生出新类。在这个过程中 原有的类称为基类,新类称为派生类。
汽车类派生出卡车类。在此过程中,我们 称汽车类为基类,卡车类为汽车类的派生 类。
面向对象程序设计提供了类的继承机制 ,该机制自动的为派生类提供了其基类 的操作和属性,大大的提高了代码的重 用率。
C++面向对象程序设计
2019/2/12
4.3.2 析构函数
派生类析构函数应用举例。
class GraduateStudent: public Student { protected: int gCount; public: ~GraduateStudent() { cout<<"Destructing GraduateStudent\n"; } };
C++面向对象程序设计 2019/2/12
4.4 多继承和虚基类
4.4.1 4.4.2 4.4.3 4.4.4
4JAVA_类的继承和派生
构造函数的使用 super用法
在Java的覆盖机制中,子类中的同名成员变量或方 法隐藏了超类的成员变量或方法,如果在子类中, 希望使用父类中的那些被子类覆盖的成员或方法, 就需要借助于super这个关键字。另外,若在子类中 调用父类的构造方法,也需要利用super实现。
super使用方法如下:
Java的继承
什么是继承 如何实现继承 构造函数的使用 继承中的覆盖现象 类之间的关系 继承层次图 如何设计好继承
什么是继承
继承和现实生活中的“继承”有相似之处,都是保留一些 父级的特性。 继承是从已有的类中派生出新的类。
新的类能吸收已有类的数据属性和行为; 并能扩展新的能力。 父类又叫超类或基类, 子类又叫派生类。
super.成员变量名称 //使用父类的成员变量 super.方法名称 //使用父类的方法
构造函数的使用 this用法
super是Java语言的关键字,用来表示直接父类。 为了区别,Java提供this关键字访问当前对象。 当在一个类中要明确指出使用当前对象本身的 变量或方法时,就可以使用this关键字代表当 前类。this的另一个用途是调用当前对象的另 一个构造方法。假如一个类中定义了几个构造 方法,可以使用this关键字引用当前类中定义 的其他构造方法。
什么是继承 如何实现继承 构造函数的使用 继承中的覆盖现象 类之间的关系 继承层次图 如何设计好继承
继承层次图
类可以实现多层继承。多层继承就是一个类的 子类还可以有子类,其原理如动物类的类层次 图
如何设计好继承
把通用操作与方法放到父类中,因为一个父类可以有 好几个子类。如果是通用的操作,放到父类中,带来 的好处是多方面的:一是避免代码重复,二是避免了 人为因素导致不一致。 不要使用受保护字段,也就是protected 字段。 尽管类的继承给开发带来了好处和方便,但如果不希 望自己的类再被扩展,也就是不希望再产生子类时, 可在类的声明之前加上final 关键字,这样此类就不能 再被继承。
《继承和派生》课件
派生类的析构函数
派生类析构函数在销毁派生类对象时 自动调用,用于释放派生类所占用的 资源。
派生类析构函数可以包含代码,用于 清理派生类所占用的资源。
派生类析构函数可以访问基类的析构 函数,通过使用`this`关键字调用基类 析构函数。
派生类析构函数可以重载基类析构函 数,以便在销毁派生类对象时执行特 定的操作。
基类析构函数的调用
在派生类的析构函数中,可以通过使用`this`关键字调 用基类的析构函数,以确保基类资源得到正确释放。
输标02入题
如果在派生类的析构函数中没有显式调用基类的析构 函数,则编译器会自动调用基类的默认析构函数。
01
03
在某些情况下,可能需要显式调用基类的析构函数, 以确保资源得到正确释放。例如,当基类包含动态分
02 继承的方式
公有继承
总结词
公有继承是指子类可以访问父类的公有成员。
详细描述
在公有继承中,子类可以访问父类的公有成员(即不加任 何修饰符的成员),这些成员在子类中保持公有属性。子 类可以继承和使用父类的公有成员,包括函数、变量、常 量等。
总结词
公有继承是实现代码复用的一种方式。
详细描述
通过公有继承,子类可以继承父类的公有成员,从而避免 重复编写相同的代码。这有助于提高代码的复用性和维护 性。
注意事项
虚函数和纯虚函数的使用 应合理规划,避免过度使 用导致程序复杂度和维护 成本增加。
继承和派生的效率问题
继承
通过共享已存在的代码, 减少代码冗余。但也可能 导致内存浪费和性能下降 。
派生
通过扩展已有类,增加新 功能或修改已有功能。但 也可能导致内存消耗增加 和性能下降。
注意事项
4. 类继承和派生
class Point{ int x, y; public: Point() { x = y = 0;
};
void main() { //这里会调用首先调用Point }
的构造函数,再调用 Point3D的构造函数。
Point3D p;
class Point3D: public Point { int z; public: Point3D() { z = 0; } };
C++面向对象程序设计
4.类的继承和派生
Agenda
• • • • • • • 1. 继承和派生的概念 2. C++中实现继承的语法 3. 继承和派生的目的 4. UML中表示继承和派生 5. C++中的类型兼容规则 6. 继承与构造函数 7. 继承与析构函数
1. 继承和派生的概念
• 类继承反映了“抽象类”和“具体类”之间的关系。例 如:
• 什么时候需要继承和派生:
– 实现代码重用。
• CTextWindow重用CWindows的Show()代码。
– 当新的问题出现,原有程序无法解决(或不能完全解
决)时,需要对原有程序进行改造(添加新的功能或
修改原有功能)。
• 前例也是一个例子:CTextWindow需要添加新的功能—文本 的处理能力。
CWindow *pw = &tw; //以下的Show是基类还是派生类的? pw->Show();
}
演示
• 例子
– 特化:字符串解析器与向量读取器。
作业3
• 实现上述例子
– 画出类图
void main() {
CompetitionStudent std;
python类的继承和派生
在Python中,类的继承和派生是通过`class`关键字和继承的语法来实现的。
类的继承允许一个类继承另一个类的属性和方法。
当一个类继承另一个类时,它会自动获得父类的所有属性和方法,并且可以添加或覆盖它们。
下面是一个简单的例子,展示了如何创建一个子类并继承父类的属性和方法:
在这个例子中,`Dog`类继承了`Animal`类。
`Dog`类覆盖了`speak`方法,使其
输出不同的声音。
除了继承属性和方法之外,子类还可以添加新的属性和方法。
例如:
在这个例子中,`Dog`类添加了一个新的方法`run`。
这样,`Dog`类不仅继承了`Animal`类的所有属性和方法,还添加了新的方法。
继承和派生
派生类构造函数调用顺序:
基类的构造函数;
子对象的构造函数;
派生类构造函数体;
二、派生类的析构函数
析构函数不能被继承; 执行派生类的析构函数时,基类的析构函数也 将被调用;
析构函数的执行顺序与构造函数严格相反;
派生类的析构函数; 基类的析构函数;
[例]分析下列程序
#include <iostream.h> class B B::~B() {public: { cout<<"B's destructor called. "<<endl; } B(); void B::Print() const B(int i); { cout<<b<<endl; } ~B(); void Print() const; private: int b; }; B::B() { b=0; cout<<"B's default constructor called. "<<endl;} B::B(int i) { b=i; cout<<"B's constructor called. "<<endl; }
回答下列问题,并说明原因。
1、派生类B中成员函数f2()能否访问基类A的成员:f1()、j1和i1? 可以访问f1()和j1,不可以访问i1; 2、能否通过派生类B的对象b访问基类A成员:f1()、j1和i1? 可以访问f1(),不可以访问j1和i1; 3、派生类C的成员函数f3()能否访问直接基类B的成员f2()、j2 和i2?能否访问间接基类A的成员: f1()、j1和i1? 可以访问直接基类中的f2()和j2以及间接基类中的f1()和j1, 不可以访问i2和i1; 4、能否通过派生类C对象c访问直接基类B中的成员:f2()、j2和i2? 能否访问间接基类A中的成员: f1()、j1和i1?
类的继承与派生共36页
15、机会是不守纪律的。——雨果
1、最灵繁的人也看不见自己的背脊。——非洲 2、最困难的事情就是认识自己。——希腊 3、有勇气承担命运这才是英雄好汉。——黑塞 4、与肝胆人共事,无字句处读书。——周恩来 5、阅读使人充实,会谈使人敏捷,写作使人精确。——培根
类的继承与派生
11、战争满足了,或曾经满足过人的 好斗的 本能, 但它同 时还满 足了人 对掠夺 ,破坏 以及残 酷的纪 律和专 制力的 欲望。 ——查·埃利奥 特 12、不应把纪律仅仅看成教育的手段 。纪律 是教育 过程的 结果, 首先是 学生集 体表现 在一切 生活领 域—— 生产、 日常生 活、学 校、文 化等领 域中努 力的结 果。— —马卡 连柯(名 言网)
类的继承与派生 谭浩强C++ppt课件
基类和派生类
对于保护继承方式与私有继承方式的情况基本相同。两者的区别就在于,基类的公有成 员与保护成员在私有继承的方式下,在派生类中不允许再往下继承,而保护继承方式则允许 继续往下传递。
可将可见性理解为可访问性。关于可访问性的另外一种规则中,称派生类对象对基类的 访问为水平访问,称派生类的派生类对基类的访问为垂直访问。则上述讨论可总结如下:
二.派生类的三种继承方式 公有继承(public)、私有继承(private)和保护继承(protected)是常用的三种继承
方式。 ⒈ 公有继承(public) 公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的
状态,而基类的私有成员仍然是私有的。 ⒉ 私有继承(private) 私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这
个派生类的子类所继承与访问。
5
基类和派生类
⒊ 保护继承(protected) 保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被 它的派生类成员函数或友元访问,而这种继承关系还可向其子类进行传递。基类的私有成员仍然 是私有的。 为了进一步理解三种不同继承方式在其成员的可见性方面的区别,下面从三种不同角度进 行讨论。
生类的关系是相对而言的。
8
基类和派生类
这就意味着:一个基类可以是另一个基类的派生类,这样便形成了复杂的继承结构,出 现了类的层次。一个基类派生出一个派生类,它又可作为另一个派生类的基类,则原来的基 类为该派生类的间接基类。其关系如右图所示。
6
基类和派生类
⑵ 基类成员对派生类成员函数的可见性: 公有成员与保护成员可见,而私有成员不可见。这里保护成员等同于公有成员。
JAVA类的继承和派生
派生类的定义
派生类定义的一般格式为: [类修饰符] class 子类名 extends 父类名{ 成员变量定义; 成员方法定义; }
派生类的定义中,用关键字extends来明确指出 它所继承的超类。 例5-1 通过继承来定义派生类
}
}
派生类的定义(续)
class AutomobileExtends{
public static void main(String args[派]){生类使用从超类中继承
Truck tc=new Truck();
的方法setN8);
tc.setCapacity(10);
x,y //继承自Point类
radius
成员方法
setX,getX,setY,getY //继承自Point类
set Radius,getRadius,getDiameter,getCircumference,
toString
//重写父类同名方法
getArea, Circle (), Circle ( int xValue, int yValue, double radiusValue )
public String toString(){
return "Center = "
+super.toString()+" Radius = " + radius;
}
……
通过super调用超类中的被重写的
toString方法
继承下的构造函数和finalize方法
继承下的构造函数的调用次序:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C++面向对象程序设计
2013年9月9日星期一
4.1.1 基类与派生类
以原有的类为基础产生新类,我们就说 从原有的类派生出新类。在这个过程中 原有的类称为基类,新类称为派生类。
汽车类派生出卡车类。在此过程中,我们 称汽车类为基类,卡车类为汽车类的派生 类。
面向对象程序设计提供了类的继承机制 ,该机制自动的为派生类提供了其基类 的操作和属性,大大的提高了代码的重 用率。
2013年9月9日星期一
C++面向对象程序设计
4.1.2 派生类的声明
C++中声明派生类的形式为:
class 派生类名: 继承方式 基类名1, 继承方 式 基类名2, …,继承方式 基类名n { 派生类的成员声明; };
声明中的“基类名”是已经存在的类的名称, “派生类名”是在已存在的类的基础上通过添 加成员而得到的新类。当派生类只有一个直接 基类的继承情况,称为单继承。当派生类同时 有多个基类的继承情况,称为多继承。C# B
从基类CMeter派生的CStick类除具有CMeter所有公有成员和保护成员 外,还有自身的私有数据成员m_nStickNum和公有成员函数DispStick()。
注意:派生类中或派生类的对象可以使用基类的公有成员(包括保护成 员),例如CStick的成员函数DispStick中调用了基类CMeter的GetPos函数
C++面向对象程序设计
2013年9月9日星期一
4.3.2 析构函数
派生类析构函数应用举例。
class GraduateStudent: public Student { protected: int gCount; public: ~GraduateStudent() { cout<<"Destructing GraduateStudent\n"; } };
C++面向对象程序设计 2013年9月9日星期一
4.4 多继承和虚基类
4.4.1 4.4.2 4.4.3 4.4.4
派生类成员的标识与访问 作用域分辨 多继承和虚基类 虚基类及其派生类的构造函数
C++面向对象程序设计
2013年9月9日星期一
4.4.1 派生类成员的标识与访问
派生类吸收了基类除构造函数和析构函数 以外的所有成员,并添加新成员得到的类 。按照派生类对象能否直接访问可以把派 生类数据成员分为两种。
C++面向对象程序设计 2013年9月9日星期一
4.2.2 私有继承
类的继承方式为私有继承的时候,基类 中的公有和保护成员被吸收后成为派生 类的私有成员,而基类的私有成员在派 生类中不可直接访问。 私有继承应用举例。P125
C++面向对象程序设计
2013年9月9日星期一
[例Ex_ClassPrivateDerived] 派生类的私有继承示例。
C++面向对象程序设计 2013年9月9日星期一
例如: class A {...} class B {...} class C:public A,private B {...} 派生类C的成员包含了基类A中成员和B中成员 以及该类本身的成员。 允许一个基类有多个派生类以及从一个基类 的派生类中再进行多个层次的派生。
派生类构造函数声明一般语法如下:
2013年9月9日星期一
C++面向对象程序设计
派生类的构造函数和析构函数被执行时,基类相应的构造函数和 析构函数也会被执行。 注意,派生类对象在建立时,先执行基类的构造函数,然后执 行派生类的构造函数。但对于析构函数来说,其顺序刚好相反, 先执行派生类的析构函数,而后执行基类的析构函数。 需要注意的是,如果在对派生类进行初始化时,需要对其基类 设置初值,则可按下列格式进行: <派生类名>(总参表):<基类1>(参数表1), <基类2>(参数表2), „, <基类n>(参数表n), 对象成员1(对象成员参数表1), 对象成 员2(对象成员参数表2), „, 对象成员n(对象成员参数表n) { ... } 构造函数总参表后面给出的是需要用参数初始化的基类名、对 象成员名及各自对应的参数表,基类名和对象成员名之间的顺序 可以是任意的,且对于使用默认构造函数的基类和对象成员,可 以不列出基类名和对象成员名。这里所说的对象成员是指在派生 类中新声明的数据成员,它属于另外一个类的对象。对象成员必 C++面向对象程序设计 2013年9月9日星期一 须在初始化列表中进行初始化。
C++面向对象程序设计 2013年9月9日星期一
4.2.3 保护继承
当类的继承方式为保护继承的时候,基 类中的公有和保护成员被吸收后成为派 生类的保护成员,只能被它的派生类成员 函数或友元访问,而基类中的私有成员在 派生类中不可直接访问。 保护继承的例子。 P126
C++面向对象程序设计
2013年9月9日星期一
作用域分辨解决的是派生类中的同名覆盖 现象。
派生类声明了和基类同名的新成员(如果是 函数成员则所带参数必须相同,否则就是函 数重载),派生类的新成员就覆盖了从基类 继承的同名成员。直接访问只能访问派生类 新增成员。为了能够访问基类同名成员,我 们采用了作用域分辨符来完成这个任务。
作用域分辨符的使用形式:
可见成员。派生类的可见成员也就是派生类的 公有成员:派生类从基类继承的公有成员和派 生类新增的公有成员. 不可见成员。派生类的不可见成员就是派生类 的私有成员和保护成员:派生类从基类继承的 私有、保护成员和派生类新增的私有、保护成 员。
C++面向对象程序设计 2013年9月9日星期一
4.4.2 作用域分辨
2013年9月9日星期一
4.3.2 析构函数
派生类的析构函数是在派生类对象生命期结 束之前对派生类新增的数据成员完成必要的 清理工作。
析构函数的作用与构造函数几乎正好相反,它在 对象删除前被自动调用,来完成一些清理工作, 也就是一些扫尾工作。 派生类析构函数执行顺序和构造函数刚好相反: 首先对派生类新增一般数据成员进行清理工作, 接着对派生类内嵌对象成员进行清理工作,最后 才是对基类继承的成员进行清理。这一点,大家 可以根据栈区“先进后出” 的特性来理解。
4.3 派生类的构造函数和析构函数B
4.3.1 构造函数 4.3.2 析构函数
C++面向对象程序设计
2013年9月9日星期一
4.3.1 构造函数
派生类对象在定义的时候必须调用派生类的 构造函数进行初始化工作,也就是为派生类 对象的数据成员赋初值。
构造函数的作用是在对象被创建时用特定的方式 构造对象,将对象初始化为一个特定的状态,使 此对象具有区别于其它对象的特征。 派生类对象的数据成员包括从基类继承的数据成 员和派生类新增的数据成员,如果派生类有内嵌对 象作为数据成员,那么派生类的数据成员还包括内 嵌对象的数据成员。派生类对象定义的时候,构 造函数需要完成上述数据成员的初始化工作。
基类名::成员名; //数据成员 基类名::成员名(参数表); //函数成员
C++面向对象程序设计 2013年9月9日星期一
4.4.3 多继承和虚基类
多继承是指一个派生类同时有多个直接基类,即一个 派生类对象含有多个基类数据成员的拷贝。由于多层 次的交叉派生关系,多继承中一个派生类可能保留某 个基类的多个实例。这种多继承的方式可使派生类具 有多个基类的特性,大大提高了程序代码的可重用性 。 多继承下派生类的定义是按下面的格式: class <派生类名> : [<继承方式1>] <基类名1>,[< 继承方式2>] <基类名2>,... { [<派生类的成员>] }; 其中的继承方式还是前面的三种:public、private 和protected。
派生类构造函数初始化时先调用基类
构造函数完成从基类继承数据成员的 初始化,接着调用内嵌对象的构造函 数完成内嵌对象数据成员的初始化, 最后才调用派生类构造函数完成新增 数据成员的初始化。
C++面向对象程序设计
2013年9月9日星期一
4.3.1 构造函数
派生类构造函数应用举例。P128
class GraduateStudent: public Student { protected: int gCount; public: GraduateStudent(int gN,float gG,int gC): Student(gN,gG) { cout<<"Constructing GraduateStudent\n"; gCount=gC; } }; C++面向对象程序设计
#include <iostream.h>
class CMeter
{public: CMeter(int nPos = 10) ~CMeter() { } { m_nPos = nPos; }
void StepIt(){ m_nPos++; }
int protected: void SetPos(int nPos) { m_nPos = nPos; } private: GetPos(){ return m_nPos; }
C++面向对象程序设计
2013年9月9日星期一
class CStick : public CMeter { int public: void DispStick(); }; void CStick:: DispStick() { 数 cout<<m_nStickNum<<’ ’; } m_nStickNum = GetPos(); // 调用基类CMeter的成员函 // 声明一个公有成员函数 // 注意分号不能省略 m_nStickNum; // 声明一个私有数据成员