面向对象程序设计II

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

2020/1/231第十六章继承与多态性§16.1继承与派生概述§16.2派生类对象的构造§16.3多态性小结2020/1/232继承与多态性是面向对象程序设计的重要特征。如果一种语言只支持类而不支持多态性,只能称其是基于对象的。如VB、Ada语言不是面向对象的,只是基于对象的。本章内容:C++语言中关于继承和多态性方面的基本概念及语法要点。基类和派生类,单继承和虚函数等。2020/1/23316.1继承与派生概述1抽象与具体(1)分类、分层分类、分层是人们表达和处理复杂事物的基本手段;正确的分类及分层是人们掌握事物间相互关系,深刻认识了事物之间异同的具体体现;分类是人类很自然的一个过程;知识存在于比较和分类之间。(2)以“生物分类学”为例生物分类学是认识生物多样性的基础;各种各样的生物将按“界、门、纲、目、科、属、种”七个层次归类。2020/1/2342020/1/2352组合与继承刻画“猫(cat)”和“豹(leopard)”两个类classCat;classLeopard;方案一———相互独立有较多的相同代码。相同的部分无法借用方案二———将Cat类的对象组合到Leopard中豹有重量、有年龄、有性别,还有猫(逻辑错误)方案三———设计一个“猫科动物(Feline)”类,将Cat、Leopard作为猫科动物的派生类。猫是猫科动物,豹是猫科动物符合“生物分类学”理论,可行。方案四———设计一个“动物(Animal)”类按“生物分类学”原理,派生各个层次的类。2020/1/236继承的概念可以用于设计复杂的系统,它提供了将系统的组成部分组织成一个继承结构的方法,以利于对系统的描述。同时它还提供了一个代码重用的结构。运用继承与派生设计程序解决实际问题需要:深刻认识实际问题,正确地分层、分类可能需要专门的知识2020/1/237BAA派生类是对基类的扩充在C++中,如果有一个类B继承了类A,或从类A派生出类B,通常称类A为基类(父类),称类B为派生类(子类)。类B不但拥有类A的属性,而且还可以拥有自己新的属性。A:父类,基类B:子类,派生类2020/1/238在C++中,继承分为单继承和多继承:单继承——派生类只有一个直接基类的继承方式;多继承——派生类有多个直接基类的继承方式。如下图所示:外部存储器软盘光盘硬盘单继承ABC单继承XYZ多继承2020/1/239由基类派生其他类的语法格式为class派生类名:继承方式基类类名{//新增加的属性和行为//或者基类成员函数的覆盖、重载};说明:基类是已经存在的类,任何已存在的类均能作基类;所声明的派生类是一个新类;继承方式有公开继承、保护继承和私有继承。这三种继承方式分别用保留字public、protected和private。2020/1/2310说明:无论那种继承方式,派生类都全部继承了基类的一切成员(基类的构造函数、拷贝构造函数和析构函数除外);从基类继承而来的成员已经成为派生类的成员,在不引起混淆的情况下,我们仍称它们为基类的成员。基类成员在派生类中的访问属性变化见下表;从基类继承而来的成员函数可以被覆盖(此时显式参数不变)也可以被重载(此时显式参数不同);派生类中可以增加新的数据成员和新的成员函数。继承提供了在已有类的基础上开发出新类的机制,可以节省重复代码的编写工作,是软件“重用技术”的基础,是刻画复杂系统的重要手段。2020/1/2311派生类定义了与基类同名的成员,在派生类中访问同名成员时屏蔽了基类的同名成员在派生类中使用基类的同名成员,显式地使用类名限定符:类名::成员classbase{public:inta,b;};classderived:publicbase{public:intb,c;};voidf(){derivedd;d.a=1;d.base::b=2;d.b=3;d.c=4;}baseabderivedabbc4321derivedd基类成员的作用域延伸到所有派生类派生类的重名成员屏蔽基类的同名成员2020/1/2312#includeiostream.hclassA{public:inta1,a2;A(inti1=0,inti2=0){a1=i1;a2=i2;}voidprint(){couta1=a1'\t'a2=a2endl;}};classB:publicA{public:intb1,b2;B(intj1=1,intj2=1){b1=j1;b2=j2;}voidprint()//定义同名函数{coutb1=b1'\t'b2=b2endl;}voidprintAB(){A::print();//派生类对象调用基类版本同名成员函数print();//派生类对象调用自身的成员函数}};2020/1/2313voidmain(){Bb;b.A::print();b.printAB();}2020/1/2314不可访问不可访问不可访问privateprivateprotectedprotectedprotectedprivateprotectedpublicpublic私有继承保护继承公有继承继承方式基类成员属性基类成员在派生类中的访问属性2020/1/23151、公有继承方式(public)基类中的每个成员在派生类中保持同样的访问权限;public成员public成员protected成员protected成员private成员public成员protected成员private成员基类派生类2020/1/23162、私有继承方式(private)基类中的每个成员在派生类中都是private成员,而且它们不能再被派生的子类所访问;public成员protected成员private成员public成员protected成员private成员基类派生类private成员private成员2020/1/23173、保护继承方式(protected)基类中的public成员和protected成员在派生类中都是protected成员,private成员在派生类中仍为private成员。public成员protected成员private成员public成员protected成员private成员基类派生类protected成员protected成员2020/1/2318#includeiostream.h//公有继承classA{public:voidget_XY(){coutEntertwonumbersofx,y:;cinxy;}voidput_XY(){coutx=x,y=y'\n';}protected:intx,y;};classB:publicA{public:intget_S(){returns;}voidmake_S(){s=x*y;}//使用基类数据成员x,yprotected:ints;};2020/1/2319classC:publicB{public:voidget_H(){coutEnteranumberofh:;cinh;}intget_V(){returnv;}voidmake_V(){make_S();v=get_S()*h;}//使用基类成员函数protected:inth,v;};2020/1/2320voidmain(){AobjA;BobjB;CobjC;coutItisobject_A:\n;objA.get_XY();objA.put_XY();coutItisobject_B:\n;objB.get_XY();objB.make_S();coutS=objB.get_S()endl;coutItisobject_C:\n;objC.get_XY();objC.get_H();objC.make_V();coutV=objC.get_V()endl;}2020/1/2321classAclassC:publicBclassB:publicAobjA.yobjA.xobjAobjB.sobjB.yobjB.xobjBxysobjC.hobjC.vobjC.sobjC.yobjC.xobjChv2020/1/2322#includeiostream.h//私有继承classA{public:voidget_XY(){coutEntertwonumbersofxandy:;cinxy;}voidput_XY(){coutx=x,y=y'\n';}protected:intx,y;};classB:privateA{public:intget_S(){returns;}voidmake_S(){get_XY();s=x*y;}private:ints;};voidmain(){BobjB;coutItisobject_B:\n;objB.make_S();coutS=objB.get_S()endl;}classB:privateAclassAobjB.sobjB.yobjB.xobjBprivate成员2020/1/2323#includeiostream.h//私有数据成员classA{public:A(){x=1;}intout(){returnx;}voidaddX(){x++;}private:intx;};classB:publicA{public:B(){y=1;}intout(){returny;}voidaddY(){y++;}private:inty;};voidmain(){Aa;Bb;b.addX();b.addY();couta.x=a.out()endl;coutb.x=b.A::out()endl;coutb.y=b.out()endl;}classB:publicAclassAb.xa.xb.y基类的私有数据成员不能在派生类中直接访问但派生类对象建立私有数据空间2020/1/2324类设计时,成员访问属性protected与private的区别。一般应用程序中只采用公共继承。在继承中,访问权限归纳如下:1、不管是什么继承方式,派生类的成员函数和友元函数都可以访问基类中的公有成员和保护成员,但不能访问私有成员;2、在公有继承时,派生类的对象只能访问公有成员,在保护继承和私有继承时,派生类的对象不能访问基类中任何成员。类中protected成员的优点是:既可以在本类中实现数据的隐藏(在类外不可被直接访问),又可以将其类内直接访问特性传递到派生类中(在派生类中可直接访问)。但private成员只能实现本类中的数据隐藏,而不能将其类内直接访问特性传递到派生类中。2020/1/232516.2派生类对象的构造通过继承关系,派生类包含了它的所有基类的成员。派生类对象的数据结构由基类中说明的数据成员和派生类中说明的数据成员共同构成。在创建派生类对象时,派生类对象的初始化,不仅要给派生类中的数据成员初始化,还要给它的基类中的数据成员初始化。如果派生类中还有子对象时,还应包含对子对象初始化。2020/1/2326构造函数的作用处理对象空间构造结构初始化数据成员基类的构造函数不被继承,派生类中需要声明自己的构造函数。声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。派生类的构造函数需要给基类的构造函数传递参数2020/1/2327派生类的构造函数派生类名::派生类名(基类所需的形参,本类成员所需的形参):基类名(参数表){本类成员初始化赋值语句;}这样处理,正符合非静态数据成员的构造时机:构造函数首部后,进入构造函数体之前。从基类继承的数据成员也不例外。2020/1/2328#includeiostream.hclassB{public:B();B(inti);~B();voidPrint();private

1 / 76
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功