《继承与派生类》PPT课件.ppt

上传人:小飞机 文档编号:5568490 上传时间:2023-07-29 格式:PPT 页数:36 大小:343.97KB
返回 下载 相关 举报
《继承与派生类》PPT课件.ppt_第1页
第1页 / 共36页
《继承与派生类》PPT课件.ppt_第2页
第2页 / 共36页
《继承与派生类》PPT课件.ppt_第3页
第3页 / 共36页
《继承与派生类》PPT课件.ppt_第4页
第4页 / 共36页
《继承与派生类》PPT课件.ppt_第5页
第5页 / 共36页
点击查看更多>>
资源描述

《《继承与派生类》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《继承与派生类》PPT课件.ppt(36页珍藏版)》请在三一办公上搜索。

1、第五章 继承与派生类,本章主要内容5.1 派生类的概念5.2 派生类的构造函数和析构函数5.3 多重继承5.4 赋值兼容规则本章重点派生类的构造函数和析构函数及它们的执行顺序本章难点 派生类的构造函数的定义格式以及多继承的构造函数的定义本章所需学时:4 学时,继承是面向对象程序设计的基本特征之一,是从已有的类基础上建立新类。继承性是面向对象程序设计支持代码重用的重要机制。面向对象程序设计的继承机制提供了无限重复利用程序资源的一种途径。通过C+语言中的继承机制,一个新类既可以共享另一个类的操作和数据,也可以在新类中定义已有类中没有的成员,这样就能大大的节省程序开发的时间和资源。,class US

2、tudentpublic:void print()coutnumberendl;coutnameendl;coutscoreendl;coutmajorendl;protected:int number;string name;float score;String major;,为什么要使用继承class Studentpublic:.void print()coutnumberendl;coutnameendl;coutscoreendl;protected:int number;string name;float score;,5.1 继承与派生类,继承是类之间定义的一种重要关系。定义类U

3、Student继承类Student时,自动得到类Student的操作和数据属性,使得程序员只需定义类Student中所没有的新成分就可完成在类UStudent的定义,这样称类UStudent继承了类Student,类Student派生了类UStudent,Student是基类(父类),UStudent是派生类(子类)。这种机制称为继承。称已存在用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。派生类可以具有基类的特性,共享基类的成员函数,使用基类的数据成员,还可以定义自己的新特性,定义自己的数据成员和成员函数。在C+语言中,一个派生类可以从一个基类派生,也可以

4、从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。,派生类的声明单继承的定义格式如下:class:public:/派生类新定义成员members;members;members;是新定义的一个类的名字,它是从中派生的,并且按指定的派生的。有以下几种形式:public:表示公有继承;private:表示私有继承,可默认声明;protected:表示保护继承,派生类除了可以从基类继承成员外,还可以增加自己的数据成员和成员函数。这些新增的成员正是派生类不同于基类的关键所在,是派生类对基类的发展。从已有类派生出新类时,可以在派生类内完成以下几种功能:可以增加新的数据成员。

5、可以增加新的成员函数。可以重新定义基类中已有的成员函数。可以改变现有成员的属性。,基类成员在派生类中的访问属性基类中的私有成员 无论哪种继承方式,基类中的私有成员不允许派生类继承,即在派生类中是不可直接访问的。基类中的公有成员当类的继承方式为公有继承时,基类中的所有公有成员在派生类中仍以公有成员的身份出现的。当类的继承方式为私有继承时,基类中的所有公有成员在派生类中都是以私有成员的身份出现的。当类的继承方式为保护继承时,基类中的所有公有成员在派生类中都是以保护成员的身份出现的。,基类中的保护成员当类的继承方式为公有继承时,基类中的所有保护成员在派生类中仍以保护成员的身份出现的。当类的继承方式为

6、私有继承时,基类中的所有保护成员在派生类中都是以私有成员的身份出现的。当类的继承方式为保护继承时,基类中的所有保护成员在派生类中仍以保护成员的身份出现的。,派生类对基类成员的访问规则派生类对基类成员的访问形式主要有以下两种:内部访问:由派生类中新增成员对基类继承来的成员的访问。对象访问:在派生类外部,通过派生类的对象对从基类继承来的成员的访问。,下面具体讨论在3种继承方式下,派生类对基类成员的访问规则。私有继承的访问规则当类的继承方式为私有继承时,基类的 public成员和 protected成员被继承后作为派生类的private成员,派生类的其他成员可以直接访问它们,但是在类外部通过派生类的

7、对象无法访问。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类成员还是通 过派生类的对象,都无法直接访问基类的private成员,但是可以通过基类提供的 public成员函数间接访问。例题分析:5.1,公有继承的访问规则 当类的继承方式为公有继承时,基类的public成员和protected成员被继承到派生类中仍作为派生类的public成员和 protected成员,派生类的其他成员可以直接访问他们。但是,类的外部使用者只能通过派生类的对象访问继承来的pllblic成员。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类成员还是通过派生类的对象,都

8、无法直接访问从基类继承来的private成员,但是可以通过基类提供的public成员函数间接访问它们。例题分析:5.3,保护继承的访问规则当类的继承方式为保护继承时,基类的public成员和protected成员,派生类的其他成员可以直接访问它们,但是在类外使用不能通过派生类的对象来访问它们。基类的private成员在保护派生类中是不可直接访问的。例题分析:5.4,5.2派生类的构造函数与析构函数,构造函数由于构造函数不能够被继承,C+提供一种机制,使得在创建派生类对象时,能够调用基类的构造函数来初始化基类数据。也就是说,派生类的构造函数必须通过调用基类的构造函数来初始化基类对象。所以,在定义

9、派生类的构造函数时除了对自己的数据成员进行初始化外,还必须负责调用基类构造函数使基类的数据成员得以初始化。父类构造函数的执行时机:定义构造子类对象时,在子类对象调用构造函数时,在子类构造函数的第一条语句前插入一条调用父类构造函数的语句,以完成对父类继承的成员的初始化操作。并且父类数据的初始值必须由子类构造函数的成员初始化列表给出。如子类构造函数中没有给出序列初始化列表,则调用父类的默认构造函数。,派生类构造函数与析构函数的执行顺序通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数:当撤消派生类对象时,则先执行派生类的折构函数,随后再执行基类的析构函数。例题分析:

10、5.5,派生类构造函数和析构函数的构造规则当基类的构造函数没有参数,或没有显式定义构造函数时,派生类可以不向基类传递参数,甚至可以不定义构造函数派生类不能继承基类中的构造函数和析构函数。当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供把参数传递给基类构造函数的途径。在C+中,派生类的构造函数的一般格式为:派生类名():基类构造函数(),子对象名(),子对象名(;,派生类构造函数的调用顺序如下:(1)调用基类的构造函数,调用顺序按照它们继承时说明的顺序。(2)调用子对象类的构造函数,调用顺序按照它们在类中说明的顺序。(3)派生类构造函数体中的内容。例题分析:5.7,说明派生类构造函数

11、的定义中可以省略对基类构造函数的调用,其条件是在基类中必须有默认的构造函数或者根本没有定义构造函数。当然,基类中没有定义构造函数,派生类根本不必负责调用基类构造函数当基类的构造函数使用一个或多个参数时,则派生类必须定义构造函数,提供将参数传递给基类构造函数途径。在有的情况下,派生类构造函数体可能为空,仅起到参数传递作用如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造由于析构函数是不带参数的,在派生类中是否定义析构函数与它所属基类无关,基类的析构函数不会因为派生类没有析构函数而得不到执行,它们是各自独立的。下面例子5.8来说明派生类的构造函数与析构函数的构造规则,#inclu

12、declass Firstint a,b;public:First()a=0;b=0;First(int x,int y)a=x;b=y;First()void print()coutn a=a b=b;class Second:public Firstint c,d;public:Second():First(1,1)c=0;d=0;Second(int x,int y):First(x+1,y+1)c=x;d=y;Second(int x,int y,int m,int n):First(m,n)c=x;d=y;Second()void print()First:print();cout

13、c=c d=d;,class Third:public Second int e;public:Third()e=0;Third(int x,int y,int z):Second(x,y)e=z;Third(int x,int y,int z,int m,int n):Second(x,y,m,n)e=z;Third()void print()Second:print();cout e=e;,main()First obj0;obj0.print();Second obj1;obj1.print();Second obj2(10,10,20,20);obj2.print();Second o

14、bj3(10,10);obj3.print();Third obj4;obj4.print();Third obj5(10,10,20);obj5.print();Third obj6(100,100,200,50,50);obj6.print();return 0;,在派生类中声明的名字支配基类中声明的同名的名字,即如果在派生类的成员函数中直接使用该名字的话,则表示使用派生类中声明的名字,而不是基类中声明的名字,如:class Xpublic:int f();class Y:public Xpublic:int f();int g();;void Y:g()f();/X:f();,5.3 调

15、整基类成员在派生类中的访问属性,访问声明我们已经知道,对于公有继承,基类的公有成员函数也就是派生类的公有成员函数,这意味着外界可以用派生类的对象调用基类的公有成员函数。但是对于私有继承,基类的公有成员函数变成了派生类的私有成员函数了。这时,外界就无法利用派生类的对象直接调用基类的成员函数,而只能通过调用派生类的成员函数(内含调用基类成员函数的语句)间接地调用基类的成员函数。,#includeclass Aint y;public:A(int x1)x=x1;void print()coutx=x;class B:private Aint y;public:B(int x1,int y1):A(

16、x1)y=y1;void print1()print();main()B b(10,20);b.print1();return 0;,上述方法虽然执行起来比较简单,但在实际应用中却可能带来不便。有时程序员可能希望基类A的个别成员还能被派生类的对象直接访问,而不是通过派生类的公有成员函数间接 访问。为此,C+提供了称为访问声明的特殊机制,可个别调整基类的某些成员,使之在派生类中保持原来的访问属性。访问声明的方法就是把基类的保护成员或公有成员直接写至私有派生类定义式中的同名段中,同时给成员名前冠以基类名和作用域标识符“:。利用这种方法,该成员就成为派生类的保护成员或公有成员了。例如,把上面的例5-

17、10基类中的print函数以 A:print的形式直接写到私有派生类B中就可以了。说明:数据成员也可以使用访问声明;访问声明中只含不带类型和参数的函数名或变量名访问声明不能改变类成员原来在基类中的成员性质对于基类中的重载函数名,访问声明将对其基类中所有同名函数起作用。,5.4 多重继承,可以为一个派生类指定多个基类,这样的继承结构称为多继承。多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个继承关系。多继承下派生类的定义格式如下:class:,;缺省的继承方式:private 例5.12给出了多继承情况下的访问特性,说明:对基类成员的访问必

18、须是无二义性的如:class X public:void f();class Y public:void f();void g();class Z:public X,public Y public:void g();void h();Z obj;obj.f()则对函数f()的访问是二义的:/无法确定访问X中或是Y中的f(),使用基类名可避免这种二义:obj.X:f();/X中的f();obj.Y:f();/Y中的f();Z类的成员访问f()时也必须避免这种二义。,多继承的构造函数与析构函数 在多继承的情况下,多个基类构造函数的调用次序是按基类在被继承时所声明的次序从左到右依次调用,与它们在派生

19、类的构造函数实现中的初始化列表出现的次序无关。派生类的构造函数格式如下:():(),(),(),其中,中各个参数包含了其后的各个分参数表。例题分析:5.13 5.14,虚基类当某一个类的多个直接基类是从另一个共同基类派生而来时,这些直接基类中从上一级基类继承来的成员就拥有相同的名称。在派生类的对象中,这些同名成员在内存中同时拥有多个拷贝。那如何进行区分呢?例5.15给出了一种方法:就是使用作用域标识符来唯一标识并访问它们。例题分析:5.15,虽然base1和base2是从同一个基类base派生而来的,但它们所对应的是基类base的不同拷贝。类derived是base1和base2的派生类,因此

20、类base是类derived的间接基类,它有两个拷贝与类derived相对应,一个是base1派生路径上的拷贝,另一个是base2派生路径上的拷贝。当类derived要访问这个间接基类 base时,必须指定要访问的是哪个路径上的 base拷贝。为了解决这种二义性,C+引入了虚基类的概念。,虚基类在C+中,如果想使这个公共的基类只产生一个拷贝,则可以将这个基类说明为虚基类。这就要求从基类派生新类时,使用关键字virtual将类base说明为虚基类。虚基类说明格式如下:class 派生类名:virtual 其中,virtual是虚基类的关键字。虚基类的说明是用在定义派生类时,写在派生类名的后面。将

21、上例用虚基类进行改写。例题分析:5.16,虚基类的初始化虚基类的初始化与一般的多继承的初始化在语法上是一样的,但构造函数的调用顺序不同。在使用虚基类机制时应该注意以下几点。如果在虚基类中定义有带形参的构造函数,并且没有定义缺省形式的构造函数,则整个继承结构中,所有直接或间接的派生类都必须在构造函数的成员初始化表中列出对虚基类构造函数的调用,以初始化在虚基类中定义的数据成员。建立一个对象时,如果这个对象中含有从虚基类继承来的成员,则虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。该派生类的其他基类对虚基类构造函数加调用都自动被忽略。若同一层次中同时包含虚基类和非虚基类,

22、应先调用虚基类的构造函数,再调用非虚基类的构造函数,最后调用派生类构造函数。,对于多个虚基类,构造函数的执行顺序仍然是先左后右,自上而下。对于非虚基类,构造函数的执行顺序仍是先左后右,自上而下。若虚基类由非虚基类派生而来,则仍然先调用基类构造函数,再调用派生类的构造函数例题分析:5.17,5.5 赋值兼容规则,概念所谓赋值兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来替代。通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员(私有成员除外),而且所有成员的访问控制属性也和基类完全相同。这样,公有派生类实际上就具备了基类的所有特性,凡基类能解决的问题,公有派生类也

23、能解决。,根据赋值兼容规则,在基类的对象可以使用的任何地方,都可以用派生类的对象来替代,但只能使用从基类继承来的成员。以下几种情况是合法的:可以用派生类对象给基类对象赋值:基类中所有的数据成员都具有派生类对应数据成员的值可以用派生类对象来初始化基类的引用可以把派生类对象的地址赋值给指向基类的指针可以把指向派生类对象的指针赋值给指向基类对象的指针例5-17给出了兼容规则的实例,说明声明为指向基类对象的指针可以指向它的公有派生类的对象允许将一个声明为指向基类的指针公有派生类的对象,但是不能将一个声明为指向派生类对象的指针指向其基类的一个对象声明为指向基类对象的指针,当其指向公有派生类对象时,只能用它来直接访问派生类中从基类继承来的成员,而不能直接访问公有派生类中定义的成员。,本章作业 5-18、5-19、5-20,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号