C程序设计基础第12章 虚函数与多态性课件.pptx

上传人:小飞机 文档编号:1828064 上传时间:2022-12-20 格式:PPTX 页数:32 大小:352.28KB
返回 下载 相关 举报
C程序设计基础第12章 虚函数与多态性课件.pptx_第1页
第1页 / 共32页
C程序设计基础第12章 虚函数与多态性课件.pptx_第2页
第2页 / 共32页
C程序设计基础第12章 虚函数与多态性课件.pptx_第3页
第3页 / 共32页
C程序设计基础第12章 虚函数与多态性课件.pptx_第4页
第4页 / 共32页
C程序设计基础第12章 虚函数与多态性课件.pptx_第5页
第5页 / 共32页
点击查看更多>>
资源描述

《C程序设计基础第12章 虚函数与多态性课件.pptx》由会员分享,可在线阅读,更多相关《C程序设计基础第12章 虚函数与多态性课件.pptx(32页珍藏版)》请在三一办公上搜索。

1、第12章 虚函数与多态性,主讲:李政伟,2,第12章 虚函数与多态性,12.1 多态性的概念12.2 虚函数的定义12.3 抽象类12.4 实例研究,3,多态性是OOP的重要特征之一。多态一词最初来源于希腊语Polumorphos,含义是具有多种形式或形态的情形。多态性:发出同样的消息被不同类型的对象接收时会导致完全不同的行为。多态性:父类型具有“引用由它派生的任何子类型”的能力。 多态的实现途径函数重载运算符重载虚函数,12.1 多态性(polymorphism)的概念,静态多态,动态多态,4,函数重载:在同一作用域内的多个函数采用相同名字,只要使用不同类型、不同数目的参数。作为重载函数:(

2、1)至少在参数个数、参数类型上有所不同。(2)使用缺省函数参数要注意二义性。如: void print(int a,int b); void print(int a,int b,int c=50); print(10,100);,12.1 多态性(polymorphism)的概念,5,12.1 多态性(polymorphism)的概念,运算符重载:对已有的运算符赋予多重含义。必要性 C+中预定义运算符其运算对象只能是标准数据类型,而不适用于用户自定义类型(如类)。实现机制 将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。,6,分类系统实现的角度静态多态性:在编译时系

3、统就能决定调用哪个函数,又称编译时的多态性。函数重载、运算符重载动态多态性:在运行过程中才动态确定操作所针对的对象。又称运行时多态。虚函数(virtual function),12.1 多态性(polymorphism)的概念,7,class Point public: Point(double i, double j) x=i; y=j; double Area() const return 0.0; private: double x, y;class Rectangle:public Point public:Rectangle(double i, double j, double k,

4、 double l);double Area() const return w*h; private:double w,h;,例12.1 非虚函数举例,8,Rectangle:Rectangle(double i, double j, double k, double l) : Point(i,j)w=k; h=l; void fun(Point ,例12.1非虚函数举例,注意事项,派生类对象指针使用时应注意的问题:(1)声明为指向基类对象的指针可以指向它的公有派生类的对象,但不允许指向它的私有派生类的对象。 (2)允许声明为指向基类对象的指针指向它的公有派生类的对象,但不允许将一个声明为指向

5、派生类对象的指针指向基类的对象。(3)声明为指向基类对象的指针,当其指向它的公有派生类的对象时,只能直接访问派生类中从基类继承下来的成员,不能直接访问公有派生类中定义的成员。要想访问其公有派生类中的成员,可将基类指针用显式类型转换方式转换为派生类指针。,10,12.3 虚函数,12.3.1 虚函数的作用同一类中不能定义名字,参数个数和类型都相同的函数,不能“重复定义”。不同层次中可以出现名字、参数个数和类型都相同而功能不同的函数。系统按照同名覆盖的原则决定调用对象。rc1.area( ) /派生类Rectangle的成员函数。rc1.Point:area( ) /基类Point的成员函数Pre

6、f.area( ),11,虚函数的声明形式virtual () 函数体 成员函数,非static成员函数有继承性,基类中定义了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。作用:通过基类指针或引用调用执行时根据指针指向的对象类型动态决定调用哪个函数。,12.3 虚函数,12,class Apublic:virtual void display() cout“A:display();,class B: public A public: void display() /自动成为虚函数 cout“B:display(); ;class C: public B public: void di

7、splay() /自动成为虚函数 cout“C:display()endl;,void fun(A *ptr)ptr-display(); void main()A a1, *p;B b1; C c1; p= ,13,虚函数的使用方法 (1) 基类中用virtual声明其为虚函数(2) 要求函数名、返回类型、参数个数和类型全部与基类的虚函数相同,根据需要重新定义函数体。(3) 定义一个指向基类对象的指针变量,使它指向同一类族中要调用该函数的对象。(4) 通过该指针变量调用此虚函数,调用的是指针变量指向的对象所属类的同名函数。,例12.2 基类与派生类中有同名函数,14,函数重载可用于普通函数和

8、类的成员函数;虚函数只能用于类的成员函数。函数重载可用于构造函数;虚函数不可以。重载成员函数必须属于同一个类,为横向;虚函数是同一类族中基类和派生类的同原型函数,为纵向。函数重载要求函数名字相同,但参数个数或类型不同;虚函数要求同一类族所有虚函数的名字、参数类型、个数完全相同。函数重载在编译时确定;虚函数在程序运行时确定。,函数重载 PK 虚函数,12.2.3 虚函数的限制,使用虚函数时应注意如下问题:(1)虚函数声明只能出现在类声明的函数原型的声明中,不能出现在函数体实现中,同时基类中只有保护成员或公有成员才能被声明为虚函数。(2)派生类中重新定义虚函数时,关键字virtual可以写也可不写

9、,为避免引起混乱,应写上该关键字。(3)动态联编只能通过成员函数来调用或通过指针、引用来访问虚函数,如果用对象名的形式来访问虚函数,将采用静态联编。(4)构造函数不能声明为虚函数,析构函数可以声明为虚函数,例12.3 基类中有非虚析构函数时的情况,class Point /基类Point类 public: Point( ) Point()coutexecuting Point destructorendl;class Circle: public Point /派生类Circle类public: Circle( ) Circle( )coutexecuting Circle destructo

10、rendl; private: int radius;int main( ) Point *p=new Circle; delete p; ,executing Point destructor,17,12.3.4 虚析构函数,用new运算符建立对象,且定义了指向基类的指针变量。用带指针参数的delete运算符撤销对象时:只执行基类析构函数,而不执行派生类的析构函数。,18,virtual Point()coutexecuting Point destructorendl;,executing Circle destructorexecuting Point destructor,例12.3

11、基类中有非虚析构函数时的情况,基类的析构函数为虚函数时,该基类的所有派生类的析构函数都自动成为虚函数,即使两者的名字不同。推荐:基类析构函数声明为虚函数。,19,12.4 纯虚函数与抽象类,12.4.1 纯虚函数基类中成员函数设为虚函数,一般并不是基类本身的要求,而是考虑到派生类的需要。基类Point没有求面积的Area函数,“点”没有面积,基类本身不需要这个函数。直接派生类Circle和间接派生类Rectangle中都需要Area函数,且功能不同。,20,12.4.1 纯虚函数,virtual float area( ) const return 0; /虚函数virtual float a

12、rea( ) const =0; /纯虚函数纯虚函数(pure virtual function):在声明虚函数时被“初始化”为0的函数。纯虚函数的声明格式:virtual 函数类型 函数名 (参数表列) =0;注: 无函数体;“=0”不表示返回值为0,只用来告知是纯虚函数; 以分号结束。,21,只有函数名字而不具备函数的功能,不能被调用。只是通知编译系统: 这里声明一个虚函数,留待派生类中定义。作用:基类中为其保留了函数名字,以便派生类根据需要对它进行定义。若基类声明了纯虚函数,而派生类没有定义,则该虚函数在派生类中仍然为纯虚函数。,12.4.1 纯虚函数,22,12.4.2 抽象类(abs

13、tract class),定义1:不能用来定义对象而只作为基类的类。定义2:带有纯虚函数的类。一种特殊的类,它为一族类提供统一的操作界面,处于继承层次结构的较上层。作用:通过它多态地使用其中的成员函数。描述了一组子类共同的操作接口,而完整的实现留给了子类。只能作为基类,不能实例化。但可以声明抽象类的指针和引用,指向并访问派生类的对象。若在派生类中对抽象类的所有纯虚函数进行了定义,派生类就成了具体类。若在派生类中没有对所有纯虚函数进行定义,则此派生类仍为抽象类。,23,例12.4 虚函数和抽象基类的应用,例12.4 虚函数和抽象基类的应用。对Point为基类的点圆圆柱体类的层次结构进行改写,要求

14、使用虚函数和抽象基类。顶层是抽象基类Shape(形状)。Point(点), Circle(圆),Cylinder(圆柱体)都是Shape类的直接派生类和间接派生类。,24,第(1)部分,class Shape /抽象基类Shapepublic: virtual float area( ) const return 0.0; virtual float volume() const return 0.0; virtual void shapeName() const =0;,25,第(2)部分,class Point: public Shape /Shape的公用派生类public: Point

15、(float=0,float=0); void setPoint(float,float); float getX( ) const return x; float getY( ) const return y; virtual void shapeName( ) const coutPoint:; friend ostream ,26,class Circle:public Point /Circle类public: Circle(float x=0,float y=0,float r=0); void setRadius(float); float getRadius( ) const;

16、virtual float area( ) const; virtual void shapeName( ) const coutCircle:; friend ostream ,第(3)部分,27,Circle:Circle(float a,float b,float r):Point(a,b),radius(r) void Circle:setRadius(float r):radius(r) float Circle:getRadius( ) const return radius;float Circle:area( ) const return 3.14159*radius*radi

17、us;ostream ,第(3)部分,28,第(4)部分,class Cylinder:public Circle /Cylinder类public: Cylinder (float x=0,float y=0,float r=0,float h=0); void setHeight(float); virtual float area( ) const; virtual float volume( ) const; virtual void shapeName( ) const coutCylinder:; friend ostream,29,Cylinder:Cylinder(float

18、a,float b,float r,float h) :Circle(a,b,r),height(h) float Cylinder:area( ) const return 2*Circle:area( )+2*3.14159*radius*height;float Cylinder:volume( ) const return Circle:area( )*height;ostream ,第(4)部分,30,int main( )Point point(3.2,4.5); Circle circle(2.4,1.2,5.6); Cylinder cylinder(3.5,6.4,5.2,10.5); point.shapeName(); coutshapeName( ); coutarea( )volume()nn;,第(5)部分,31,pt=,第(5)部分,32,Thank You,The End of Ch.12.,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号