C语言8虚函数_第1页
C语言8虚函数_第2页
C语言8虚函数_第3页
C语言8虚函数_第4页
C语言8虚函数_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

1、第八章第八章 虚函数虚函数 C+中的动态联编是通过虚函数实现的,虚函数允许函数调用与函数体之间的联系在运行时才建立。8.1 引入派生类后的对象指针引入派生类后的对象指针指向基类的指针可以指向其公有派生类对象指向基类的指针可以指向其公有派生类对象 根据继承方式的概念,按公有继承的方式产生的派生类中,必然包含了原来基类中的全部成员。因此,一个公有派生类的对象可以提供其基类对象的全部行为,则在程序中可以把一个公有派生类对象当作其基类对象来处理,那么,指向基类的指针自然也可以指向其公有派生类对象。【例】【例】基类指针、派生类指针、基类对象和派生类对象四者间组合的使用情况示例基类指针、派生类指针、基类对

2、象和派生类对象四者间组合的使用情况示例#include class A int a; public: A(int i=1) a=i; void print( ) couta=aendl; int geta( ) return a;class B:public A int b; public: B(int j=2) b=j; void print( ) coutb=bprint(); pb=&bb; pb-print(); pa=&bb; pa-print(); bb.print(); coutgeta()getb();则错误,因基类则错误,因基类指针仅能看到派生类中的基类部分,

3、指针仅能看到派生类中的基类部分,而不能直接访问公有派生类中定义而不能直接访问公有派生类中定义的成员,但可采用强制类型转换的成员,但可采用强制类型转换(B*)pa)-getb();结果结果:a=10b=20a=1b=201 /基类指针可以指向基类对象基类指针可以指向基类对象/派生指针可以指向派生类对象派生指针可以指向派生类对象/基类指针可指向它的公有派生类对象,但不许指向它的私有派生类对象。基类指针可指向它的公有派生类对象,但不许指向它的私有派生类对象。/错误,派生类指针不可以直接指向基类对象错误,派生类指针不可以直接指向基类对象8.2 虚函数的定义及使用虚函数的定义及使用1 1虚函数的作用虚函

4、数的作用 上例中,虽然基类指针pa指向派生类对象bb(即pa=&bb),但语句pa-print()所调用的函数仍是基类对象的print()。这是由于虽然一个基类指针可以指向其派生类对象,但指针本身的属性并没有改变,因此,系统认为它所指向的仍然是一个基类对象,于是就只能调用其基类的成员函数print()。但在派生类中已经改变了这个函数的实现,即在派生类中又定义了一个同名的print()函数,而这种改变在静态联编时编译器并不知道,以致于造成和我们期望的结果不统一。 所以,必须通知编译器这种可能的改变,即需要进行动态联编,其方法就是在基类中将可能发生改变的成员函数声明为虚函数。否则,若要调用

5、派生类中的成员函数print(),只能采用显式的方法:bb.print(); 或采用对指针强制类型转换的方法(B*)pa)-print(); 基类用虚函数提供了一个派生类对象都具有的共同界面,派生类又各自对虚函数定义自己的具体实现,即常说的“同一接口,多种方法”。这样,使得程序既简洁又具有扩充性,并能帮助程序员处理越来越复杂的程序。2 2虚函数的定义虚函数的定义 在基类中的成员函数原型前加上关键字virtual,其格式如下:class class 类名类名 virtual virtual 类型类型 函数名(参数表);函数名(参数表); ; ; 当一个类的成员函数说明为虚函数后,就可以在该类的(

6、直接或间接)派生类中定义与其基类虚函数原型相同的函数。这时,当用基类指针指向这些派生类对象时,系统会自动用派生类中的同名函数来代替基类中的虚函数。也就是说,当用基类指针指向不同派生类对象时,系统会在程序运行中根据所指向对象的不同,自动选择适当的函数,从而实现了运行时的多态性。【例】【例】虚函数的定义与应用举例。虚函数的定义与应用举例。#include “iostream.h”class Base public: virtual void show() cout”base classn”; ;class Der1: public Base public: void show() cout”der

7、ived class 1 n”; ;class Der2: public Base public: void show() coutshow(); p=&dobj1; p-show(); p=&dobj2; p-show(); 程序的运行结果:程序的运行结果:base classderived class 1derived class 2说明:说明:(1)在基类中,用virtual可将其public或protected成员函数声明为虚函数。(2)在派生类中对基类声明的虚函数进行重新定义时,virtual可写可不写。(3)虚函数被重新定义时,其函数原型必须与基类中的函数原型完全相

8、同,包括函数名、返回类型、参数个数和参数类型的顺序。(4)通过虚函数实现了运行时的多态性。(5)只有通过基类指针访问虚函数时,才能获得运行时的多态性,使用对象名对象名.虚函数名虚函数名( )的方式时,虚函数的调用是通过静态联编实现的。(6)当一个函数在基类被声明为虚函数后,不管经历多少层派生,都将保持其虚拟性。 (7)只有类的成员函数才能声明为虚函数,全局函数及静态成员函数不能声明为虚函数。(8)构造函数不能是虚函数,但析构函数可以是虚函数。3虚函数与重载函数的关系虚函数与重载函数的关系 虚函数可以在一个或多个派生类中被重新定义,因此,属于函数重载的情况,但这种重载与一般的函数重载是不同的。

9、例:class Base public: virtual void fun1( ); virtual void fun2( ); virtual void fun3( ); void fun4( );class Derived: public Base public: void fun1( ); /是虚函数是虚函数 void fun2(int i ); /作为普通函数重载,虚特性消失作为普通函数重载,虚特性消失 char fun3( ); /错误,因为只有返回类型不同,应删去错误,因为只有返回类型不同,应删去 void fun4( ); /普通函数重载普通函数重载;void main() Ba

10、se *bp; Derived d; bp=&d; bp-fun1( ); /调用调用Derived:fun1( ) bp-fun2( ); /调用调用Base:fun2( ) bp-fun4( ); /调用调用Base:fun4( )4多重继承与虚函数多重继承与虚函数class Base1 public: virtual void fun( );class Base2 public: void fun( );class Derived: public Base1, public Base2 public: void fun( );void main() Base1 *p1; Base

11、2 *p2; Derived d; p1=&d; p1-fun( ); /调用调用derived:fun( ) p2=&d; p2-fun( ); /调用调用Base2:fun( )8.3 纯虚函数与抽象类纯虚函数与抽象类 纯虚函数纯虚函数是在基类中只声明虚函数而不给出具体的函数定义体,将它的具体定义放在各派生类中,称此虚函数为纯虚函数。 纯虚函数的声明如下:(注:要放在基类的定义体中) virtual virtual 函数原型函数原型=0=0; 其中:函数原型的格式同前面所学格式一样,要包括函数返回值的类型、函数名、圆括号、形参及其类型等。 声明了纯虚函数的类,称为抽象类抽象

12、类。使用纯虚函数时应注意:使用纯虚函数时应注意:(1)抽象类中可以有多个纯虚函数。(2)抽象类中也可以定义其他非纯虚函数。(3)不能声明抽象类的对象,但可以声明指向抽象类的指针变量和引用变量。并且抽象类不能用做参数类型、函数返回值或显式转换的类型。(4)如果派生类中没有重新定义基类中的纯虚函数,只是继承它,则此派生类仍是一个抽象类。(5)从抽象类可以派生出具体或抽象类,但不能从具体类派生出抽象类。(6)在一个复杂的类继承结构中,越上层的类抽象程度越高,有时甚至无法给出某些成员函数的实现,显然,抽象类是一种特殊的类,它一般处于类继承结构的较上层。(7)引入抽象类的目的,主要是为了能将相关类组织在一个类继承结构中,并通过抽象类来为这些相关类提供统一的操作接口。【例】【例】设计一个抽象类shape,它表示具有形状的东西,体现了抽象的概念,在它下面可以派生出多种具体形状,比如三角形、矩形。 #includeclass Shape protected: double x,y; public: void set(double i, double j) x=i; y=j; virtual void area()=0; /声明纯虚函数声明纯虚函数 ;class Triangle: public Shape public: void area()

温馨提示

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

评论

0/150

提交评论