您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 企业文化 > 第八章_继承与多态(C++程序设计(第2版)吴乃陵)
继承(inheritance):继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构。体现了由简单到复杂的认识过程。多态性(polymorphism):多态性是考虑在不同层次的类中,以及在同一类中,同名的成员函数之间的关系问题。函数的重载,运算符的重载,属于编译时的多态性。以虚函数为基础的运行时的多态性是面向对象程序设计的标志性特征。体现了类推和比喻的思想方法。第八章继承与多态第八章继承与多态8.1继承与派生的概念8.4虚基类(选读)8.3多重继承与派生类成员标识8.6多态性与虚函数8.5派生类应用讨论8.2派生类的构造函数与析构函数8.1继承与派生的概念层次概念是计算机的重要概念。通过继承(inheritance)的机制可对类(class)分层,提供类型/子类型的关系。C++通过类派生(classderivation)的机制来支持继承。被继承的类称为基类(baseclass)或超类(superclass),新的类为派生类(derivedclass)或子类(subclass)。基类和派生类的集合称作类继承层次结构(hierarchy)。层次概念:派生反映了事物之间的联系,事物的共性与个性之间的关系。派生与独立设计若干相关的类,前者工作量少,重复的部分可以从基类继承来,不需要单独编程。8.1继承与派生的概念8.1.1类的派生与继承8.1.2公有派生与私有派生派生类的定义:class派生类名:访问限定符基类名1《,访问限定符基类名2,……,访问限定符基类名n》{《《private:》成员表1;》//派生类增加或替代的私有成员《public:成员表2;》//派生类增加或替代的公有成员《protected:成员表3;》//派生类增加或替代的保护成员};//分号不可少其中基类1,基类2,……是已声明的类。在派生类定义的类体中给出的成员称为派生类成员,它们是新增加成员,它们给派生类添加了不同于基类的新的属性和功能。派生类成员也包括取代基类成员的更新成员。8.1.1类的派生与继承基类1基类2……基类n派生类1派生类2基类派生类1派生类2(a)多重继承(b)单继承图8.1多重继承与单继承一个基类可以直接派生出多个派生类派生类可以由多个基类共同派生出来,称多重继承。8.1.1类的派生与继承多重继承:如果一个派生类可以同时有多个基类,称为多重继承(multiple-inheritance),这时的派生类同时得到了多个已有类的特征。单继承:派生类只有一个直接基类的情况称为单继承(single-inheritance)。8.1.1类的派生与继承在派生过程中,派生出来的新类同样可以作为基类再继续派生出更新的类,依此类推形成一个层次结构。直接参与派生出某类称为直接基类,而基类的基类,以及更深层的基类称为间接基类。类族:同时一个基类可以直接派生出多个派生类。这样形成了一个相互关联的类族。如MFC就是这样的族类,它由一个CObject类派生出200个MFC类中的绝大多数。多层次继承:编制派生类时可分四步吸收基类的成员改造基类成员发展新成员重写构造函数与析构函数8.1.1类的派生与继承不论是数据成员,还是函数成员,除构造函数与析构函数外全盘接收声明一个和某基类成员同名的新成员,派生类中的新成员就屏蔽了基类同名成员称为同名覆盖(override)派生类新成员必须与基类成员不同名,它的加入保证派生类在功能上有所发展。派生编程步骤:8.1.1类的派生与继承第二步中,新成员如是成员函数,参数表也必须一样,否则是重载。第三步中,独有的新成员才是继承与派生的核心特征。第四步是重写构造函数与析构函数,派生类不继承这两种函数。不管原来的函数是否可用一律重写可免出错。例题:基类与派生类的定义和实现访问控制,亦称为继承方式,是对基类成员进一步的限制。访问控制也是三种:公有(public)方式,亦称公有继承保护(protected)方式,亦称保护继承私有(private)方式,亦称私有继承。8.1.2公有派生与私有派生访问限定符两方面含义:派生类成员(新增成员)函数对基类(继承来的)成员的访问(调用和操作),和从派生类对象之外对派生类对象中的基类成员的访问。即内部访问和对象访问。(1)公有继承当类的继承方式为公有继承时,基类的public成员和protected成员被继承到派生类中仍作为派生类的public成员和protected成员,派生类的其他成员可以直接访问它们。但是,类的外部使用者只能通过派生类的对象访问继承来的public成员。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类成员还是通过派生类的对象,都无法直接访问从基类继承来的private成员,但是可以通过基类提供的public成员函数间接访问它们。8.1.2公有派生与私有派生访问限定符两方面含义:派生类成员(新增成员)函数对基类(继承来的)成员的访问(调用和操作),和从派生类对象之外对派生类对象中的基类成员的访问。即内部访问和对象访问。(2)保护继承当类的继承方式为保护继承时,基类的public成员和protected成员被继承到派生类中都作为派生类的protected成员,派生类的其他成员可以直接访问它们,但是类的外部使用者不能通过派生类的对象来访问它们。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类成员还是通过派生类的对象,都无法直接访问基类的private成员。8.1.2公有派生与私有派生访问限定符两方面含义:派生类成员(新增成员)函数对基类(继承来的)成员的访问(调用和操作),和从派生类对象之外对派生类对象中的基类成员的访问。即内部访问和对象访问。(3)私有继承当类的继承方式为私有继承时,基类的public成员和protected成员被继承后作为派生类的private成员,派生类的其他成员可以直接访问它们,但是在类外部通过派生类的对象无法访问。基类的private成员在私有派生类中是不可直接访问的,所以无论是派生类成员还是通过派生类的对象,都无法直接访问从基类继承来的private成员,但是可以通过基类提供的public成员函数间接访问。不可直接访问不可直接访问private不可直接访问protectedprotected不可直接访问protectedpublic保护派生不可直接访问不可直接访问private不可直接访问protectedprotected可直接访问publicpublic公有派生在派生类对象外访问派生类对象的基类成员在派生类中对基类成员的访问限定基类中的访问限定派生方式不可直接访问不可直接访问private不可直接访问privateprotected不可直接访问privatepublic私有派生派生类构造函数和析构函数的执行顺序通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数;当撤消派生类对象时,则先执行派生类的析构函数,随后再执行基类的析构函数。8.2派生类的构造函数与析构函数例基类和派生类的构造函数及析构函数的执行顺序。#includeiostream.hclassBase{public:Base(){coutConstructingbaseclass\n;}//基类的构造函数~Base(){coutDestructingbaesclass\n;}//基类的析构函数};classDerive:publicBase{public:Derive(){coutConstructingderivedclass\n;}//派生类的构造函数~Derive(){coutDestructingderivedclass\n;}//派生类的析构函数};main(){Deriveop;return0;}派生类构造函数的定义:派生类名::派生类名(参数总表):基类名1(参数名表1)《,基类名2(参数名表2),……,基类名n(参数名表n)》,《成员对象名1(成员对象参数名表1),……,成员对象名m(成员对象参数名表m)》{……//派生类新增成员的初始化;}//所列出的成员对象名全部为新增成员对象的名字注意:在构造函数的声明中,冒号及冒号以后部分必须略去。所谓不能继承并不是不能利用,而是把基类的构造函数作为新的构造函数的一部分,或者讲调用基类的构造函数。基类名仅指直接基类,写了底层基类,编译器认为出错。冒号后的基类名,成员对象名的次序可以随意,这里的次序与调用次序无关。8.2派生类的构造函数与析构函数派生类构造函数各部分执行次序:1.调用基类构造函数,按它们在派生类定义的先后顺序,顺序调用。2.调用成员对象的构造函数,按它们在类定义中声明的先后顺序,顺序调用。3.派生类的构造函数体中的操作。8.2派生类的构造函数与析构函数注意:在派生类构造函数中,只要基类不是使用缺省构造函数都要显式给出基类名和参数表。如果基类没有定义构造函数,则派生类也可以不定义,全部采用系统给定的缺省构造函数。如果基类定义了带有形参表的构造函数时,派生类就应当定义构造函数。8.2派生类的构造函数与析构函数析构函数:析构函数的功能是作善后工作。只要在函数体内把派生类新增一般成员处理好就可以了,而对新增的成员对象和基类的善后工作,系统会自己调用成员对象和基类的析构函数来完成。析构函数各部分执行次序与构造函数相反,首先对派生类新增一般成员析构,然后对新增对象成员析构,最后对基类成员析构。【例8.1】由在册人员类公有派生学生类。我们希望基类和派生类共享相同的公有接口,只能采用公有派生来实现。基类:classPerson{stringIdPerson;//身份证号,18位数字stringName;//姓名TsexSex;//性别enumTsex{mid,man,woman};intBirthday;//生日,格式1986年8月18日写作19860818stringHomeAddress;//家庭地址public:Person(string,string,Tsex,int,string);//构造函数Person();//缺省的构造函数~Person();//析构函数voidSetName(string);//修改名字stringGetName(){returnName;}//提取名字voidSetSex(Tsexsex){Sex=sex;}//修改性别TsexGetSex(){returnSex;}//提取性别voidSetId(stringid){IdPerson=id;}//修改身份证号stringGetId(){returnIdPerson;}//提取身份证号voidSetBirth(intbirthday){Birthday=birthday;}//修改生日intGetBirth(){returnBirthday;}//提取生日voidSetHomeAdd(string);//修改住址stringGetHomeAdd(){returnHomeAddress;}//提取住址voidPrintPersonInfo();//输出个人信息};接口函数:派生的学生类:classStudent:publicPerson{//定义派生的学生类stringNoStudent;//学号coursecs[30];//30门课程与成绩public:Student(stringid,stringname,Tsexsex,intbirthday,stringhomeadd,stringnostud);//注意派生类构造函数声明方式Student();//缺省派生类构造函数~Student();//派生类析构函数SetCourse(string,int);//课程设置intGetCourse(string);//查找成绩voidPrintStudentInfo();//打印学生情况};structcourse{stringcourse
本文标题:第八章_继承与多态(C++程序设计(第2版)吴乃陵)
链接地址:https://www.777doc.com/doc-3359026 .html