ImageVerifierCode 换一换
格式:PPT , 页数:37 ,大小:655KB ,
资源ID:8270907      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.docduoduo.com/d-8270907.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第14章多态.ppt)为本站会员(hwpkd79526)主动上传,道客多多仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知道客多多(发送邮件至docduoduo@163.com或直接QQ联系客服),我们立即给予删除!

第14章多态.ppt

1、第14章多态,-2-,本章内容安排,多态的概念 虚函数实现多态 虚函数机制 纯虚函数与抽象类,-3-,赋值兼容性规则,每一个派生类的对象,都是基类的一个对象。赋值兼容规则是指在公有派生情况下,一个公有派生类的对象可以当作基类的对象使用,反之则禁止。 派生类的对象可以赋值给基类对象。 派生类的对象可以初始化基类的引用。 指向基类的指针也可以指向派生类。 通过基类对象名、指针只能使用从基类继承的成员,-4-,派生类对象赋值给基类对象,Mammal m(3,5); Dog d(2,3,LAB); m=d; 通过m不能访问或间接访问breed成员,-5-,基类对象赋值给派生类对象,Mammal m(2

2、, 3); Dog d(3,4, LAB); d=m;,X,?,-6-,派生类对象初始化基类引用,Dog d(2,3, LAB); Mammal 虽然rp是c的引用,但只能访问基类部分数据和方法,-7-,派生类对象地址赋值基类指针,Dog d(2,3, LAB); Mammal *pd= /基类指针可指向派生类对象 通过pd只能访问基类部分的数据和接口,-8-,Mammal基类,class Mammal public:Mammal() : age(1) cout “Mammal constructor .n“; Mammal() cout “Mammal destructor .n“; voi

3、d speak() const cout “Mammal speak!n“; void move() const cout “Mammal, move one stepn“; protected:int age; ;,-9-,Dog类,class Dog : public Mammal public:Dog() cout “Dog constructor .n“; Dog() cout “Dog destructor n“; void wagTail() cout “Wagging tail .n“; void speak() const cout “Woof!n“; void move()

4、const cout “Dog moves 5 steps .n“; ;,Dog类中重写了speak和move方法,同时增加了wagTail方法。,-10-,测试程序,int main() Mammal *pDog = new Dog;pDog-move();pDog-speak();delete pDog; pDog=NULL;return 0; ,在堆中创建Dog对象,使用Mammal类指针pDog指向它。 因为pDog的类型为Mammal指针类型,会调用Mammal类的move和speak方法。编译时期进行的函数调用绑定。 尽管pDog指向的是Dog对象,但只能调用基类方法。,-11-,

5、一种期望,void speak( Mammal *pAnimal) pAnimal-speak(); int main() Mammal *pDog = new Dog;speak(pDog);Mammal *pCat = new Cat;speak(pCat);delete pDog; pDog=NULL;delete pCat; pCat=NULL;return 0; ,定义通用的处理函数speak,形参指向Mammal的指针,可以接收Dog或Cat对象地址 希望能够调用实际传递对象的speak方法,统一处理不同的对象。,由于编译期静态绑定,导致2次调用的都是基类的speak。,-12-,

6、引入多态,在基类中,将子类中都会存在并需要重写的方法声明为虚函数(virtual),就会引入多态的效果。 定义基类的指针或引用,使其指向或引用基类或派生类的对象,调用虚函数时,系统将调用实际所指向对象的方法。 使用基类指针或引用调用方法,不用关心实际所指向的对象,是一种运行时多态,编译器编译时未做绑定,而是在运行时根据实际对象临时决策。,-13-,多态的变化,class Mammal public:Mammal() : age(1) cout “Mammal constructor .n“; Mammal() cout “Mammal destructor .n“; virtual void

7、speak() const cout “Mammal speak!n“; void move() const cout “Mammal, move one stepn“; protected:int age; ;,通过virtual关键词将speak声明为虚函数。,-14-,多态的变化,class Dog : public Mammal public:Dog() cout “Dog constructor .n“; Dog() cout “Dog destructor n“; void wagTail() cout “Wagging tail .n“; virtual void speak()

8、 const cout “Woof!n“; void move() const cout “Dog moves 5 steps .n“; ;,基类中的speak声明为virtual后,派生类中重写的方法自动成为虚函数,但明确指出是一种良好编程习惯。 从Dog再派生子类时,看Dog头文件,可判断speak为虚函数。,-15-,测试程序,int main() Mammal *pDog = new Dog;pDog-move();pDog-speak();delete pDog; pDog=NULL;return 0; ,在堆中创建Dog对象,使用Mammal类指针pDog指向它。 由于将speak

9、声明为虚函数,通过pDog调用speak时调用的将是Dog类的方法。而move方法没有声明为虚函数,通过pDog只能调用Mammal类的move方法。,-16-,多态的要点,实现多态的3个基本条件 基类中声明虚函数; 子类中重写虚函数,函数签名与基类完全相同; 定义基类指针或引用,通过指针或引用调用虚函数。,-17-,本章内容安排,多态的概念 虚函数实现多态 虚函数机制 纯虚函数与抽象类,-18-,完整示例:Mammal类,class Mammal public:Mammal() : age(1) Mammal() virtual void speak() const cout “Mammal

10、 speak!n“; protected:int age; ;,-19-,完整示例:子类,class Dog : public Mammal public:virtual void speak() const cout “Woof!n“; ; class Cat : public Mammal public:virtual void speak() const cout “Meow!n“; ;,派生类中重写基类的虚函数,并且函数签名完全一致,为多态做好准备。,-20-,完整示例:子类,class Horse : public Mammal public:virtual void speak()

11、 const cout “Whinny!n“; ; class Pig : public Mammal public:virtual void speak() const cout “Oink!n“; ;,-21-,测试程序,int main() Mammal* array5;Mammal* ptr;int choice, i;,array是一个指针数组,含有5个元素,每个元素是1个Mammal类型的指针。,-22-,测试程序,int main() for (i = 0; i choice;switch (choice)case 1: ptr = new Dog; break;case 2:

12、ptr = new Cat; break;case 3: ptr = new Horse; break;case 4: ptr = new Pig; break;default: ptr = new Mammal; break;arrayi = ptr;,在堆中创建对象,使用基类指针指向所创建的对象。,-23-,测试程序,#include int main() for (i=0; i speak();delete arrayi;return 0; ,array是一个指针数组,arrayi是Mammal类型指针,通过其调用speak方法实现多态效果。 不用关心指针实际指向的对象类型,只需要调用s

13、peak方法,系统多态性帮助我们调用正确的方法版本。,-24-,本章内容安排,多态的概念 虚函数实现多态 虚函数机制 纯虚函数与抽象类,-25-,对象的构建(无虚函数),创建派生类对象时,首先调用基类的构造函数,再调用派生类的构造函数。 每个派生类对象有2个部分:基类部分由基类构造函数构建,派生类部分由派生类构造函数构建。,-26-,对象的构建(含虚函数),类中声明虚函数后,多数编译器将为每个类建立虚函数表(v-table),在每个对象中插入1个指针,指向对应的虚函数表。 定义Mammal对象时,vptr指向该类的虚函数表,Mammal类的虚函数表,-27-,对象的构建(含虚函数),定义Dog

14、类对象时,先构建Mammal部分,此时vptr指向基类的虚函数表,再构建Dog部分时,将vptr替换指向Dog类的虚函数表。,Mammal类的虚函数表,Dog类的虚函数表,-28-,多态的要点,实现多态的3个基本条件 基类中声明虚函数; 子类中重写虚函数,函数签名与基类完全相同; 定义基类指针或引用,通过指针或引用调用虚函数。,基类中声明虚函数,子类中没有重写,不产生多态,直接调用基类中的方法。 子类中扩展的方法,基类中没有定义,通过基类指针或引用禁止调用(语法错误) 子类中声明虚函数,子类中重写但签名不同,不产生多态,直接调用的基类中的方法。 按值传递对象时,不能实现多态,赋值时会产生切片效

15、果。,-29-,基类指针不能访问子类特有方法,如果Dog类中扩展了wagTail方法,但Mammal类中没有wagTail方法。通过基类指针不允许访问wagTail方法。 Mammal *pDog = new Dog; pDog-wagTail(); Dog *pRealDog = dynamic_cast (pDog); if(pRealDog)pRealDog-wagTail();,X,如果pDog确实指向1个Dog对象,可通过dynamic_cast将其转换为Dog类型指针,从而可以调用wagTail方法。 dynamic_cast进行运行时类型检查,若转换失败,会返回空指针。但尽量避免

16、这种强制转换。,-30-,对象不能实现多态,void valueFunction( Mammal mammalValue) mammalValue.speak(); void ptrFunction (Mammal *pMammal) pMammal-speak(); void refFunction (Mammal ,通过指针或引用才能实现多态,传递对象不能实现多态,-31-,多态的补充说明,应该将析构函数声明为虚函数,如果希望所写的类被继承并多态执行。 不声明虚析构函数情况下,基类指针指向堆中创建的子类对象,执行delete操作时,将会产生内存泄漏 声明虚析构函数情况,执行delete时,

17、由于多态效果,调用子类的析构函数,从而引起基类析构函数调用。 构造函数不能声明为虚函数。 使用虚函数实现多态增强了程序的灵活性,但由于维护虚函数表,会带来运行时的开销。,-32-,本章内容安排,多态的概念 虚函数实现多态 虚函数机制 纯虚函数与抽象类,-33-,Shape类,class Shape public:Shape() virtual Shape() virtual double getArea() return -1; virtual double getPerim() return -1; ;,形状类是其它具体形状类型的基类,计算面积、周长和绘图功能对shape类实际上没有多大的意

18、义。,-34-,Circle类,const double PI=3.14; class Circle : public Shape public:Circle(double newRadius) : radius( newRadius ) virtual Circle() virtual double getArea() return PI * radius * radius; virtual double getPerim() return 2 * PI * radius; private:double radius; ;,Circle类重写了基类的2个虚函数。,-35-,Rectangle

19、类,class Rectangle : public Shape public:Rectangle(double newLen, double newWidth):length(newLen), width(newWidth) virtual Rectangle() virtual double getArea() return length * width; virtual double getPerim() return 2 * length + 2 * width; virtual double getLength() const return length; virtual doubl

20、e getWidth() const return width; private:double width;double length; ;,Rectangle类重写了基类的2个虚函数,-36-,将Shape声明为抽象数据类型,Shape是各种形状的基类,但定义Shape类对象并没有意义,Shape更应该作为一种抽象概念。 将Shape类中的虚函数定义为纯虚函数,表明Shape是一种抽象概念(抽象类)。 纯虚函数只需要给出声明,通常情况下不给出纯虚函数的定义(函数体) C+禁止定义抽象类对象; 抽象类基础上派生的类,应该重写基类的纯虚函数,若没有重写,该类仍然是抽象类。,-37-,抽象Shape类,class Shape public:Shape() virtual Shape() virtual double getArea() = 0;virtual double getPerim() = 0; ;,Shape类是抽象类,不允许实例化。Shape类的子类必须重写Shape类的纯虚函数后才能实例化。 抽象类给出所有子类应该遵循的抽象接口,通常不在抽象类中定义数据成员。,

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报