C++面向对象程序设计第九章多态性与虚函数

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

13
【例9.1】虚函数的作用(改造例8.11)(P278)
class graduate:public undergraduate, public teacher // 从两个类继承 {public: void setinfo(int n, char* strname, char s, char* strfrom, float sc, float sa) { id = n; strcpy(name, strname); sex = s; strcpy(from, strfrom); score = sc; salary = sa; } graduate( ) { setinfo(1, "jetty", 'M', "china", 90, 1000); } void showinfo() { cout<<endl<<"ID: "<<id<<endl<<"name: "<<name <<endl<<"sex: "<<sex<<endl<<"from: "<<from <<endl<<"score: "<<score <<endl<<"salary: "<<salary; } };
8
9.3
纯虚函数与抽象类
被标明为不具体实现的虚成员函数为纯虚函数;其声明格式为: 被标明为不具体实现的虚成员函数为纯虚函数;其声明格式为: virtual 函数类型 函数名 参数表 ; 函数名(参数表 参数表)=0; 不能有实例对象的类即为抽象类,唯一的用途是被继承,一个抽 不能有实例对象的类即为抽象类,唯一的用途是被继承, 象类至少具有一个虚函数。 象类至少具有一个虚函数。 抽象类为抽象和设计的目的而建立, 抽象类为抽象和设计的目的而建立,将有关的数据和行为组织在 一个继承层次结构中,保证派生类具有要求的行为。 一个继承层次结构中,保证派生类具有要求的行为。对于暂时 无法实现的函数,可以声明为纯虚函数,留给派生类去实现。 无法实现的函数,可以声明为纯虚函数,留给派生类去实现。 派生类实现纯虚函数的参数要与父类纯虚函数声明的参数相同。 派生类实现纯虚函数的参数要与父类纯虚函数声明的参数相同。 抽象类不能定义对象,但可以声明抽象类的指针或引用。 抽象类不能定义对象,但可以声明抽象类的指针或引用。通过改 变指针或引用的具体地址,指向相应的派生类的对象, 变指针或引用的具体地址,指向相应的派生类的对象,以便实 现运行时的多态。 现运行时的多态。 派生类如果没有定义全部纯虚函数的操作,继承了部分纯虚函数, 派生类如果没有定义全部纯虚函数的操作,继承了部分纯虚函数, 则仍然是抽象类。 则仍然是抽象类。 【例9.3】纯虚函数和抽象类 】
12
【例9.1】虚函数的作用(改造例8.11)(P278)
class teacher:virtual public person // 虚继承 {public: void setinfo(int n, char* strname, char s, char* strfrom, float sa) { person::setinfo(n, strname, s, strfrom); salary = sa; } teacher( ) { setinfo(2, "rose", 'F', "American", 2000); } void showinfo( ) { person::showinfo(); cout<<endl<<"salary: "<<salary; } protected: float salary; };
多态包含多态重载多态强制多态参数多态静态多态动态多态前期联编编译阶段多态后期联编运行时多态92虚函数函数定义时用关键字virtual声明的函数即为虚函数921虚函数的作用922虚析构函数对比发现采用虚函数后虽然在主函数中都是同样用基类的指针pp调用函数showinfo但在运行时根据所指的不同对象调用了各对象所属类的showinfo函数输出了相应的信息实现了动态多态
11
【例9.1】虚函数的作用(改造例8.11)(P278)
class undergraduate:virtual public person // 虚继承 {public: void setinfo(int n, char* strname, char s, char* strfrom, float sc) { person::setinfo(n, strname, s, strfrom); score = sc; } undergraduate( ) { setinfo(1, "jetty", 'M', "china", 90); } void showinfo( ) { person::showinfo( ); cout<<endl<<"score: "<<score; } protected: float score; };
14
ID: 1 【例9.1】虚函数的作用(改造例8.11)(P278)
void main( ) { person* pp; person p; pp = &p; pp->showinfo( ); undergraduate u; pp = &u; pp->showinfo( ); teacher t; pp = &t; pp->showinfo( ); graduate g; pp = &g; pp->showinfo( ); }
7
9.2.2虚析构函数
【例9.2】虚析构函数示例 】
通过声明基类的析构函数为虚析构函数,从 这个基类派生的所有类的析构函数均自动为 虚析构函数,即使这些函数不同名, 这样在用基类的指针释放对象时,就能根据 基类指针所指的不同对象调用不同类的析构 函数,达到了多态的效果。 正是由于这个原因,在设计类时,往往 把基类的析构函数设计成了虚析构函数。
6
9.2.1虚函数的作用
在使用虚函数实现动态多态时要注意以下几点: 在使用虚函数实现动态多态时要注意以下几点: (1)如果函数的声明和实现分开的话,那么 )如果函数的声明和实现分开的话,那么virtual关键字 关键字 只能用来说明函数的原型,即在声明函数的时候使用, 只能用来说明函数的原型,即在声明函数的时候使用,不 能用在函数的定义中。 能用在函数的定义中。 (2)虚函数在基类与派生类中的声明(包括函数名,返回 )虚函数在基类与派生类中的声明(包括函数名, 值类型和参数表列)必须完全一样, 值类型和参数表列)必须完全一样,才能实现运行时的多 这一点与函数重载实现静态多态是不同的, 态。这一点与函数重载实现静态多态是不同的,利用函数 重载实现静态多态时,函数的参数必须有所区别, 重载实现静态多态时,函数的参数必须有所区别,要么参 数个数有区别,要么参数类型有区别。 数个数有区别,要么参数类型有区别。 (3)基类中定义了虚函数,派生类中无论是否说明,同原 )基类中定义了虚函数,派生类中无论是否说明, 型函数都自动为虚函数。 型函数都自动为虚函数。 (4)只有类的非静态成员函数才能声明为虚函数。虚函数 )只有类的非静态成员函数才能声明为虚函数。 只能用于类内的函数上, 只能用于类内的函数上,不属于任何类的普通函数是不能 作为虚函数的。 作为虚函数的。 (5)内联函数不能是虚函数。 )内联函数不能是虚函数。 (6)构造函数不能是虚函数。 )构造函数不能是虚函数。 (7)析构函数通常是虚函数。 )析构函数通常是虚函数。
15
【例9.2】虚析构函数示例(P282)
#include <iostream.h> void main() class base { base *pb = new derived; { delete pb; } public: virtual ~base( ) ~base( ) {cout<<endl <<"base destructor"; } 再次编译运行结果如下: 再次编译运行结果如下: 运行结果如下: 运行结果如下: }; derived destructor base destructor class derived:public base base destructor { public: ~derived( ) {cout<<endl <<"derived destructor"; } }; 16
9
改造第八章习题2
#include <iostream.h> class A {public: virtual void f( ) { cout<<"A f"<<endl;} }; class B:public A {public: void f( ) { cout<<"B f"<<endl;} }; class C:public B {public: void f( ) { cout<<"C f"<<endl;} }; void main( ) { A a; B b; C c; A *p; a.f( ); b.f( ); c.f( ); p = &a; p->f( ); p = &b; p->f( ); p = &c; p->f( ); }
【例9.3】纯虚函数和抽象类(P284)
运行结果: 运行结果: Af Bf Cf Af Bf Cf
10
【例9.1】虚函数的作用(改造例8.11)(P278)
#include <iostream.h> #include <string.h> class person {public: void setinfo(int n, char* strname, char s, char* strfrom) { id = n; strcpy(name, strname); sex = s; strcpy(from, strfrom); } person( ) { setinfo(1, "jetty", 'M', "china"); } virtual void showinfo( ) { cout<<endl<<"ID: "<<id <<endl<<"name: "<<name <<endl<<"sex: "<<sex <<endl<<"from: "<<from; } protected: int id; char name[10]; char sex; char from[20]; };
函数定义时 用关键字virtual声明的函数即为虚函数
9.2.1虚函数的作用 . . 虚函数的作用 9.2.2虚析构函数 . . 虚析构函数
5
9.2.1虚函数的作用
改造第八章习题2 改造第八章习题2 【例9.1】虚函数的作用(改造例 】虚函数的作用(改造例8.11) )
对比发现,采用虚函数后,虽然在主函数中都是 同样用基类的指针pp调用函数showinfo,但在运行时 根据所指的不同对象调用了各对象所属类的showinfo 函数输出了相应的信息,实现了动态多态。 这种用法很常见,只需要在定义基类时指定相应 的虚函数,就可以在以后通过基类的指针调用该虚函 数,这样就能在运行时根据所指的对象类型调用不同 类的函数实现动态多态。 注意如果不用指针的话,直接通过对象加点的方 式,就不需要虚函数了,这个时候,将会调用相应类 中的函数,这就是函数的同名覆盖。如果想调用基类 中的同名函数就必须通过基类名加域作用符的方式调 用。
name: jetty sex: M from: china ID: 1 name: jetty sex: M from: china score: 90 ID: 2 name: rose sex: F from: American salary: 2000 ID: 1 name: jetty sex: M from: china score: 90 salary: 1000
2
第九章 多态性与虚函数
9.1 多态性概念 9.2 虚函数 9.3 纯虚函数与抽象类 9.4 综合例子3来自9.1多态性概念
多态,就是发送同一种消息,不同的对象 会有不同的动作。
重载多态 强制多态 参数多态 动态多态 包含多态 前期联编 编译阶段多态 后期联编 运行时多态 静态多态
多态
4
9.2
虚函数
C++面向对 C++面向对 象程序设计
内蒙古科技大学
1
目 录
第一章 第二章 第三章 第四章 第五章 第六章 第七章 第八章 第九章 第十章 第十一章 第十二章 概述 C++程序设计初步 函数 数组和指针 类与对象 静态成员与友员 运算符重载 继承与派生 多态性与虚函数 模板 流类库与输入输出 命名空间与异常处理
相关文档
最新文档