《多态性课件》由会员分享,可在线阅读,更多相关《多态性课件(36页珍藏版)》请在金锄头文库上搜索。
1、第6章 多态性,Visual C+与面向对象程序设计教程,授 课 内 容,6.1 多态性概述 6.2 派生类对象替换基类对象 6.3 虚函数 6.4 抽象类 6.5 运算符重载,6.1 多态性概述,多态性含义 多态性的形式,多态性含义,实现“一种接口,多种方法”的技术 某类的对象在接受同样的消息时,做出不同的响应,多态性的形式,编译时多态性 编译器对源程序进行编译时就可以确定所调用的是哪一个函数,编译时多态性通过重载来实现; 函数重载 运算符重载 运行时多态性 在程序运行过程中根据具体情况来确定调用的是哪一个函数; 虚函数,编译时多态性函数重载(兔子逃生 ),class 兔子 public:
2、void 逃生(老鹰a)“兔子蹬鹰”; void 逃生(狼 b)“动如脱兔”; ;,void main() 狼 y; 兔子 x; x.逃生(y); ,运行时多态性虚函数( cat or dog? ),class 宠物 public: void char* speak() cout zzz; ; ; class 猫 : public 宠物 public: void char* speak() cout miao!miao!; ; class 狗 : public宠物 public: void char* speak() cout wang!wang!; ;,例: cat or dog?(续),v
3、oid main() 宠物 *p; /p为宠物类指针 猫 cat1; /定义猫类对象 狗 dog1; /定义狗类对象 /根据用户输入将猫或狗对象地址赋给p指针,例如用户输入1,则执行p = p-speak(); ,注意,派生类对象替换基类对象,6.2 派生类对象替换基类对象,原则: 凡是基类对象出现的场合都可以用公有派生类对象取代 形式 (1)派生类对象给基类对象赋值 (2)派生类对象可以初始化基类对象的引用 (3)可以令基类对象的指针指向派生类对象,即将派生类对象的地址传递给基类指针,例6-1 派生类对象替换基类对象,#include class Pet /基类 public: void S
4、peak() coutHow does a pet speak ?endl; ; class Cat : public Pet /派生类 public: void Speak() coutmiao!miao!endl; ;,例6-1 派生类对象替换基类对象(续一),class Dog : public Pet /派生类 public: void Speak() coutwang!wang!endl; ; void main() Pet*p1, *p2, *p3,obj; /基类对象指针p1, 基类对象obj Dog dog1; Cat cat1; obj = dog1; /用Dog类对象给Pe
5、t类对象赋值 obj.Speak();,例6-1 派生类对象替换基类对象(续二),p1 = ,运行结果: How does a pet speak ? How does a pet speak ? How does a pet speak ? How does a pet speak ? How does a pet speak ? How does a pet speak ?,用虚函数!,6.3 虚函数,定义: 在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数 语法: virtual 函数返回类型 函数名(参数表) 函数体 用途: 实现多态性,通过指向派生类的基类指针
6、,访问派生类中同名覆盖成员函数,,例6-2 虚函数实现多态性,#include class Pet /基类 public: virtual void Speak() coutHow does a pet speak ?endl; ; class Cat : public Pet /派生类 public: virtual void Speak() coutmiao!miao!endl; ;,虚函数的使用限制,应通过指针或引用调用虚函数,而不要以对象名调用虚函数说明语句 在派生类中重定义的基类虚函数仍为虚函数,同时可以省略virtual关键字 不能定义虚构造函数,可以定义虚析构函数,虚函数的声明形
7、式,例: class B public: virtual Print();/定义虚函数 ; class D:public B public: virtual Print(); ;,关于虚函数,当在派生类中定义了一个同名的成员函数时,只要该成员函数的参数个数和相应类型以及它的返回类型与基类中同名的虚函数完全一样,则无论该成员函数是否使用 virtual修饰,它都将成为一个虚函数。 基类B声明成员函数virtual Print()为虚函数,则派生类D中的Print()函数自动成为虚函数。 关键字 virtual 指示C+编译器对调用虚函数进行动态联编,这种多态性是程序运行到此处才动态确定的,所以称
8、为运行时的多态性。不过,使用虚函数并不一定产生多态性,也不一定使用动态联编。例如,在调用中对虚函数使用成员名限定,可以强制C+对该函数的调用使用静态联编。,关于赋值兼容,赋值兼容性规则是指在需要基类对象的地方可以使用公有派生类的对象来替代。通过公有继承,派生类继承了基类除了构造函数和析构函数之外的所有成员,所以,凡是基类能够工作的地方,派生类都能够正常工作。 赋值兼容性规则主要包括以下几种情况: 1) 派生类的对象可以赋值给基类对象。 2)派生类的对象可以初始化基类的引用。 3)派生类的地址可以赋值给指向基类的指针。,例: 使用虚函数,#include class B public: void
9、 Print() coutB calledendl; virtual void PrintVirtul() coutVirtul: B calledendl; ;,class D:public B public: void Print() coutD calledendl; virtual void PrintVirtul() coutVirtul: D calledendl; ;,void main() D d1; B b1; D *pD1=new D; B *pB1=new B; coutPrint(); pB1-Print(); B *pB2=new D; D d2; B ,例: 使用虚
10、函数(续),例: 使用虚函数(续),pB2-Print(); d22.Print(); D d3; B b3; D *pD3=new D; B *pB3=new B; coutPrintVirtul(); pB3-PrintVirtul(); coutPrintVirtul(); D d4; B ,没有使用虚函数,没有使用赋值兼容规则的结果 D called B called D called B called 没有使用虚函数,使用赋值兼容规则的结果 B called B called 使用虚函数函数,没有使用赋值兼容规则的结果 Virtul D called Virtul B called
11、Virtul D called Virtul B called 使用虚函数的结果函数,使用赋值兼容规则结果 Virtul D called Virtul D called,6.4 抽象类,纯虚函数 virtual 返回类型 函数名(参数表)=0 纯虚函数是为了实现多态性而存在,具体实现只能在派生类中完成。 抽象类 至少包含一个纯虚函数的类称为抽象类 抽象类为其所有子类提供了统一的操作界面,使其派生类具有一系列统一的方法。,抽象类的使用要求,抽象类不能实例化 抽象类只作为基类被继承 可以定义指向抽象类的指针或引用,例6-3 抽象宠物类的实现,#include #include class Pet
12、 /基类 char m_strName20; intm_nAge; char m_strColor12; public:char m_strType10; Pet(char *,int ,char *); char* GetName() return m_strName; int GetAge() return m_nAge; char* GetColor() return m_strColor; virtual void Speak() = 0; virtual void GetInfo() ;,例6-3 抽象宠物类的实现(续1),Pet:Pet(char *name,int age,cha
13、r *color) strcpy(m_strName,name); m_nAge=age; strcpy(m_strColor,color); strcpy(m_strType,pet); ,例6-3 抽象宠物类的实现(续2),class Cat : public Pet /派生类 public: Cat(char *name,int age, char *color):Pet(name,age,color) void Speak() cout Sound of speak : miao!miao!endlendl; void GetInfo(); ; void Cat:GetInfo() c
14、out The cats name : GetName()endl; cout The cats age : GetAge() endl; cout The cats color: GetColor()endl; ,例6-3 抽象宠物类的实现(续3),class Dog : public Pet/派生类 public: Dog(char *name,int age, char *color):Pet(name,age,color) void Speak() cout Sound of speak : wang!wang!endlendl; void GetInfo(); ; void Dog:
15、GetInfo() cout The dogs name : GetName()endl; cout The dogs age : GetAge() endl; cout The dogs color: GetColor()endl; ,例6-3 抽象宠物类的实现(续4),void main() Pet*p1;/基类对象指针p1 p1 = new Cat(MiKey,1,Blue);/动态生成Cat类对象 p1-GetInfo(); p1-Speak(); delete p1; p1 = new Dog(BenBen,2,Black);/动态生成Dog类对象 p1-GetInfo(); p1-
16、Speak(); delete p1; ,6.5 运算符重载,重载运算符主要用于对类的对象的操作 形式: :operator () ,例6-4 复数加法运算,#include class Complex double m_fReal, m_fImag; public: Complex(double r = 0, double i = 0): m_fReal(r), m_fImag(i) double Real()return m_fReal; double Imag()return m_fImag; Complex operator +(Complex,例6-4 复数加法运算(续1),Complex Complex:operator + (C