程序设计实习PPT课件_第1页
程序设计实习PPT课件_第2页
程序设计实习PPT课件_第3页
程序设计实习PPT课件_第4页
程序设计实习PPT课件_第5页
已阅读5页,还剩45页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

-,1,程序设计实习,第十四讲继承,-,2,内容提要,基本概念:继承、基类、派生类派生类的成员组成、可见性派生类的构造、析构派生类与基类的指针类型转换,-,3,继承与派生的概念,继承:在定义一个新的类B时,如果该类与某个已有的类A相似(指的是B拥有A的全部特点),那么就可以把A作为一个基类,而把B作为基类的一个派生类(也称子类)。派生类是通过对基类进行修改和扩充得到的在派生类中,可以扩充新的成员变量和成员函数派生类一经定义后,可以独立使用,不依赖于基类派生类拥有基类的全部成员,包括:(private、protected、public)属性和(private、protected、public)方法在派生类的各个成员函数中,不能访问基类中的private成员,-,4,继承与派生的概念,派生类可以定义一个和基类成员同名的成员,这叫覆盖。在派生类中访问这类成员时,缺省的情况是访问派生类中定义的成员。要在派生类中访问由基类定义的同名成员时,要使用作用域符号:继承和派生机制大大地提高了软件的可重用性和可扩充性继承是在复杂计算系统的分析/设计/实现过程中,表达子问题之间相似性的一种机制:在需要解决的问题中,有多个相似的概念每个概念用一个类表示把这些概念中相同的部分抽取出来,作为基类每个概念中的独有部分,作为基类的派生类派生类的成员包括:基类的成员,派生类中定义的成员,-,5,需要继承机制的例子:,所有的学生都有一些共同属性和方法,比如姓名,学号,性别,成绩等属性,判断是否该留级,判断是否该奖励之类的方法而不同的学生,比如中学生,大学生,研究生,又有各自不同的属性和方法,比如大学生有系的属性,而中学生没有,研究生有导师的属性,中学生竞赛、特长加分之类的属性如果为每类学生都编写一个类,显然会有不少重复的代码,浪费比较好的做法是编写一个“学生”类,概括了各种学生的共同特点,然后从“学生”类派生出“大学生”类,“中学生”类,“研究生类”,-,6,classCStudentprivate:charszName20;intnAge;intnSex;public:boolIsThreeGood();intSetSex(intnSex_)nSex=nSex_;voidSetName(char*szName_)strcpy(szName,szName_);/.;/派生类的写法是:类名:public基类名classCUndergraduateStudent:publicCStudentprivate:intnDepartment;public:boolIsThreeGood.;/覆盖boolCanBaoYan().;,-,7,classCGraduatedStudent:publicCStudentprivate:intnDepartment;charszMentorName20;public:intCountSalary().;,-,8,使用继承必须满足的逻辑关系:,如果写了一个基类A,又写了基类A的派生类B,那么要注意,“一个B对象也是一个A对象”这个命题从逻辑上成立,是A派生出B为合理派生的必要条件如上面的学生例子:一个大学生当然也是一个学生每个类都是一个子问题存在继承关系的类之间,所表达的一定是有相似关系的子问题不要为了重用代码而定义类之间的继承关系,-,9,使用继承容易犯的错误,如果写了一个CMan类代表男人,后来又发现需要一个CWoman类来代表女人,仅仅因为CWoman类和CMan类有共同之处,就让CWoman类从CMan类派生而来,是不合理的。因为“一个女人也是一个男人”从逻辑上不成立好的做法是概括男人和女人共同特点,写一个CHuman类,代表抽象的“人”,然后CMan和CWoman都从CHuman派生,-,10,使用继承容易犯的错误,如果编写了一个表示“点”的类classPointprivate:intx,y;public:Point(int=0,int=0);Point();如果希望编写一个“圆”的类Circle,圆是有圆心,圆心就是一个点,那么怎么处理圆类和点类的关系呢?能否让Circle类从Point类派生而来?,-,11,如果因为圆心是一个点,就将Circle类从Point类派生而来,就是错误的做法。因为,一个圆不是一个点。在Circle类里包含一个Point成员对象,则是合理的,这符合一个圆里有个特殊的点叫圆心这个逻辑,使用继承容易犯的错误,-,12,classCirclepublic:Circle(doubler=0.0,intx=0,inty=0);Circle();private:PointCenter;doubleradius;Circle:Circle(doubler,inta,intb):Center(a,b)radius=r;Circle:Circle(),-,13,使用继承容易犯的错误,如果要写一个小区养狗管理程序,需要写一个“业主”类,还需要写一个“狗”类而狗是有“主人”这个属性的,主人当然是业主那么能否让“狗”从“业主”派生出来?,-,14,使用继承容易犯的错误,为“狗”类设一个“业主”类的成员对象为“业主”类设一个“狗”类的对象数组,是比较好的做法,-,15,用类名:成员名的方式指明要访问的是那个类的成员,voidderived:access()j=5;/errori=5;/引用的是派生类的ibase:i=5;/引用的是基类的ifunc();/派生类的base:func();/基类的derivedobj;obj.i=1;obj.base:i=1;,Base:i,i,Obj占用的存储空间,classbaseintj;public:inti;voidfunc();,classderived:publicbasepublic:inti;voidaccess();voidfunc();,基类和派生类有同名成员的情况:,-,16,另一种存取权限说明符:protected,基类的private成员:可以被下列函数访问基类的成员函数基类的友员函数基类的public成员:可以被下列函数访问基类的成员函数基类的友员函数派生类的成员函数派生类的友员函数其他的函数基类的protected成员:可以被下列函数访问基类的成员函数基类的友员函数派生类的成员函数派生类的友员函数,-,17,classFatherprivate:intnPrivate;/私有成员public:intnPublic;/公有成员protected:intnProtected;/保护成员;classSon:publicFathervoidAccessFather()nPublic=1;/ok;nPrivate=1;/wrongnProtected=1;/OK,访问从基类继承的protected成员Fatherf;f.nProtected=1;/ok,访问基类对象的protected成员,保护成员,-,18,main()Fatherf;Sons;f.nPublic=1;/Oks.nPublic=1;/Okf.nProtected=1;/errorf.nPrivate=1;/errors.nProtected=1;/errors.nPrivate=1;/error,-,19,classBugprivate:intnLegs;intnColor;public:intnType;Bug(intlegs,intcolor);voidPrintBug();classFlyBug:publicBug/FlyBug是Bug的派生类intnWings;public:FlyBug(intlegs,intcolor,intwings);,派生类的构造函数,-,20,Bug:Bug(intlegs,intcolor)nLegs=legs;nColor=color;/错误的FlyBug构造函数:FlyBug:FlyBug(intlegs,intcolor,intwings)nLegs=legs;/不能访问nColor=color;/不能访问nType=1;/oknWings=wings;/正确的FlyBug构造函数:FlyBug:FlyBug(intlegs,intcolor,intwings):Bug(legs,color)nWings=wings;,表达式中可以出现:FlyBug构造函数的参数、常量,-,21,main()FlyBugfb(2,3,4);fb.PrintBug();fb.nType=1;fb.nLegs=2;/error.nLegsisprivate,-,22,在创建派生类的对象时,需要调用基类的构造函数:初始化派生类对象中从基类继承的成员。在执行一个派生类的构造函数之前,总是先执行基类的构造函数调用基类构造函数的两种方式显式方式:在派生类的构造函数中,为基类的构造函数提供参数derived:derived(arg_derived-list):base(arg_base-list)隐式方式:在派生类的构造函数中,省略基类构造函数时,派生类的构造函数则自动调用基类的默认构造函数派生类的析构函数被执行时,执行完派生类的析构函数后,自动调用基类的析构函数,FlyBugfb(2,3,4);fb.PrintBug();fb.nType=1;fb.nLegs=2;/error.nLegsisprivate,-,23,#includeclassBasepublic:intn;Base(inti):n(i)coutBasenconstructedendl;Base()coutBasendestructedendl;classDerived:publicBasepublic:Derived(inti):Base(i)coutDerivedconstructedendl;Derived()coutDeriveddestructedendl;main()DerivedObj(3);,-,24,输出结果:Base3constructedDerivedconstructedDeriveddestructedBase3destructed,-,25,classFlyBug:publicBugintnWings;SomeClassObj1,Obj2;public:FlyBug(intlegs,intcolor,intwings);FlyBug(intlegs,intcolor,intwings):Bug(legs,color),Obj1(5),Obj2(4).,包含成员对象的派生类的构造函数,表达式中可以出现:FlyBug构造函数的参数、常量,表达式中可以出现:FlyBug构造函数的参数、常量,-,26,在创建派生类的对象时,在执行一个派生类的构造函数之前调用基类的构造函数:初始化派生类对象中从基类继承的成员调用成员对象类的构造函数:初始化派生类对象中成员对象派生类的析构函数被执行时,执行完派生类的析构函数后,调用成员对象类的析构函数调用基类的析构函数,-,27,public继承的赋值兼容规则,派生类的对象可以赋值给基类对象b=d;派生类对象可以初始化基类引用base如果派生方式是private或protected,则上述三条不可行,classbase;classderived:publicbase;baseb;derivedd;,-,28,基类与派生类的指针强制转换,派生类对象的指针可以直接赋值给基类指针ptrBase=程序员要保证ptrBase指向的是一个Derived类的对象,否则会出错,-,29,#includeusingnamespacestd;classBaseprotected:intn;public:Base(inti):n(i)coutBasenconstructedendl;Base()coutBasendestructedendl;voidPrint()coutBase:n=nendl;,-,30,classDerived:publicBasepublic:intv;Derived(inti):Base(i),v(2*i)coutDerivedconstructedendl;Derived()coutDeriveddestructedendl;voidFunc();voidPrint()coutDerived:v=vendl;coutDerived:n=nv实际上是objDerived.n的存放空间,n,v,pDerived,objBase,objDerived,n,v,-,36,直接基类与间接基类,类A派生类B,类B可再派生类C,类C派生类D,类A是类B的直接基类类B是类C的直接基类,类A是类C的间接基类类C是类D的直接基类,类A、B是类D的间接基类在声明派生类时,派生类的首部只需要列出它的直接基类派生类的首部不要列出它的间接基类派生类沿着类的层次自动向上继承它的间接基类派生类的成员包括派生类自己定义的成员直接基类中定义的成员间接基类的全部成员,-,37,#includeclassBasepublic:intn;Base(inti):n(i)coutBasenconstructedendl;Base()coutBasendestructedendl;,-,38,classDerived:publicBasepublic:Derived(inti):Base(i)coutDerivedconstructedendl;Derived()coutDeriveddestructedendl;,-,39,classMoreDerived:publicDerivedpublic:MoreDerived():Derived(4)coutMoreDerivedconstructedendl;MoreDerived()coutMoreDeriveddestructedendl;main()MoreDerivedObj;,-,40,输出结果:Base4constructedDerivedconstructedMoreDerivedconstructedMoreDeriveddestructedDeriveddestructedBase4destructed,-,41,多继承,一个类可以从多个基类派生而来,以继承多个基类的成员。这种派生称作“多重继承”classderived:access-specifier1base1,access-specifier2base2,;access-specifieri可以是private、protected、public之一,-,42,需要多继承的例子,公司人事管理程序销售人员类有销售额属性经理类有下属人数属性开发人员类销售经理既有销售员的属性,又有经理的属性,-,43,多继承的派生类构造函数,classbase1inti;public:base1(intn)i=n;classbase2intj;public:base2(intn)j=n;classderived:publicbase1,publicbase2public:derived(intx);derived:derived(intx):base1(x),base2(0),-,44,多重继承中,派生类对象创建时,先按继承顺序调用基类的构造函数,然后再调用派生类的构造函数如果派生类是封闭类,那么成员对象的构造函数在基类的构造函数调用结束后依次调用,最后才调用派生类的构造函数,多重继承中,派生类对象的创建过程按继承顺序调用基类的构造函数依次调用成员对象的构造函数调用派生类的构造函数,-,45,多继承中基类的构造函数调用:classBasepublic:intval;Base()coutBaseConstructorendl;Base()coutBaseDestructorendl;classBase1:publicBase;classBase2:publicBase;classDerived:publicBase1,publicBase2;,-,46,main()Derivedd;输出结果:BaseConstructorBaseConstructorBaseDestructorBaseDestructor基类Base的构造函数和析构函数都被调用两次,base,base2,base1,derived,-,47,多重继承的二义性,classbase1private:in

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论