您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > C++面向对象程序设计第九章多态性与虚函数
1C++面向对象程序设计内蒙古科技大学2目录第一章概述第二章C++程序设计初步第三章函数第四章数组和指针第五章类与对象第六章静态成员与友员第七章运算符重载第八章继承与派生第九章多态性与虚函数第十章模板第十一章流类库与输入输出第十二章命名空间与异常处理3第九章多态性与虚函数9.1多态性概念9.2虚函数9.3纯虚函数与抽象类9.4综合例子49.1多态性概念多态,就是发送同一种消息,不同的对象会有不同的动作。多态包含多态重载多态强制多态参数多态静态多态动态多态前期联编编译阶段多态后期联编运行时多态59.2虚函数函数定义时用关键字virtual声明的函数即为虚函数9.2.1虚函数的作用9.2.2虚析构函数69.2.1虚函数的作用对比发现,采用虚函数后,虽然在主函数中都是同样用基类的指针pp调用函数showinfo,但在运行时根据所指的不同对象调用了各对象所属类的showinfo函数输出了相应的信息,实现了动态多态。这种用法很常见,只需要在定义基类时指定相应的虚函数,就可以在以后通过基类的指针调用该虚函数,这样就能在运行时根据所指的对象类型调用不同类的函数实现动态多态。注意如果不用指针的话,直接通过对象加点的方式,就不需要虚函数了,这个时候,将会调用相应类中的函数,这就是函数的同名覆盖。如果想调用基类中的同名函数就必须通过基类名加域作用符的方式调用。改造第八章习题2【例9.1】虚函数的作用(改造例8.11)79.2.1虚函数的作用在使用虚函数实现动态多态时要注意以下几点:(1)如果函数的声明和实现分开的话,那么virtual关键字只能用来说明函数的原型,即在声明函数的时候使用,不能用在函数的定义中。(2)虚函数在基类与派生类中的声明(包括函数名,返回值类型和参数表列)必须完全一样,才能实现运行时的多态。这一点与函数重载实现静态多态是不同的,利用函数重载实现静态多态时,函数的参数必须有所区别,要么参数个数有区别,要么参数类型有区别。(3)基类中定义了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。(4)只有类的非静态成员函数才能声明为虚函数。虚函数只能用于类内的函数上,不属于任何类的普通函数是不能作为虚函数的。(5)内联函数不能是虚函数。(6)构造函数不能是虚函数。(7)析构函数通常是虚函数。89.2.2虚析构函数通过声明基类的析构函数为虚析构函数,从这个基类派生的所有类的析构函数均自动为虚析构函数,即使这些函数不同名,这样在用基类的指针释放对象时,就能根据基类指针所指的不同对象调用不同类的析构函数,达到了多态的效果。正是由于这个原因,在设计类时,往往把基类的析构函数设计成了虚析构函数。【例9.2】虚析构函数示例99.3纯虚函数与抽象类被标明为不具体实现的虚成员函数为纯虚函数;其声明格式为:virtual函数类型函数名(参数表)=0;不能有实例对象的类即为抽象类,唯一的用途是被继承,一个抽象类至少具有一个虚函数。抽象类为抽象和设计的目的而建立,将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现。派生类实现纯虚函数的参数要与父类纯虚函数声明的参数相同。抽象类不能定义对象,但可以声明抽象类的指针或引用。通过改变指针或引用的具体地址,指向相应的派生类的对象,以便实现运行时的多态。派生类如果没有定义全部纯虚函数的操作,继承了部分纯虚函数,则仍然是抽象类。【例9.3】纯虚函数和抽象类10改造第八章习题2#includeiostream.hclassA{public:virtualvoidf(){coutAfendl;}};classB:publicA{public:voidf(){coutBfendl;}};classC:publicB{public:voidf(){coutCfendl;}};voidmain(){Aa;Bb;Cc;A*p;a.f();b.f();c.f();p=&a;p-f();p=&b;p-f();p=&c;p-f();}运行结果:AfBfCfAfBfCf11【例9.1】虚函数的作用(改造例8.11)(P278)#includeiostream.h#includestring.hclassperson{public:voidsetinfo(intn,char*strname,chars,char*strfrom){id=n;strcpy(name,strname);sex=s;strcpy(from,strfrom);}person(){setinfo(1,jetty,'M',china);}virtualvoidshowinfo(){coutendlID:idendlname:nameendlsex:sexendlfrom:from;}protected:intid;charname[10];charsex;charfrom[20];};12【例9.1】虚函数的作用(改造例8.11)(P278)classundergraduate:virtualpublicperson//虚继承{public:voidsetinfo(intn,char*strname,chars,char*strfrom,floatsc){person::setinfo(n,strname,s,strfrom);score=sc;}undergraduate(){setinfo(1,jetty,'M',china,90);}voidshowinfo(){person::showinfo();coutendlscore:score;}protected:floatscore;};13【例9.1】虚函数的作用(改造例8.11)(P278)classteacher:virtualpublicperson//虚继承{public:voidsetinfo(intn,char*strname,chars,char*strfrom,floatsa){person::setinfo(n,strname,s,strfrom);salary=sa;}teacher(){setinfo(2,rose,'F',American,2000);}voidshowinfo(){person::showinfo();coutendlsalary:salary;}protected:floatsalary;};14【例9.1】虚函数的作用(改造例8.11)(P278)classgraduate:publicundergraduate,publicteacher//从两个类继承{public:voidsetinfo(intn,char*strname,chars,char*strfrom,floatsc,floatsa){id=n;strcpy(name,strname);sex=s;strcpy(from,strfrom);score=sc;salary=sa;}graduate(){setinfo(1,jetty,'M',china,90,1000);}voidshowinfo(){coutendlID:idendlname:nameendlsex:sexendlfrom:fromendlscore:scoreendlsalary:salary;}};15【例9.1】虚函数的作用(改造例8.11)(P278)voidmain(){person*pp;personp;pp=&p;pp-showinfo();undergraduateu;pp=&u;pp-showinfo();teachert;pp=&t;pp-showinfo();graduateg;pp=&g;pp-showinfo();}ID:1name:jettysex:Mfrom:chinaID:1name:jettysex:Mfrom:chinascore:90ID:2name:rosesex:Ffrom:Americansalary:2000ID:1name:jettysex:Mfrom:chinascore:90salary:100016【例9.2】虚析构函数示例(P282)#includeiostream.hclassbase{public:~base(){coutendlbasedestructor;}};classderived:publicbase{public:~derived(){coutendlderiveddestructor;}};voidmain(){base*pb=newderived;deletepb;}运行结果如下:basedestructorvirtual~base()再次编译运行结果如下:deriveddestructorbasedestructor17【例9.3】纯虚函数和抽象类(P284)#includeiostream.hclassa{public:virtualvoidf()=0;virtualvoidg()=0;};classb:publica{public:voidf(){coutendlbf;}};classc:publicb{public:voidf(){coutendlcf;}voidg(){coutendlcg;}};voidmain(){a*pa;bx;cy;pa=&y;pa-f();pa-g();}//error;由于b类没有实现纯虚函数g,仍为抽象类,故不能生成对象实例18【例9.4】综合举例(P285)//person.h#ifndef_PERSON#define_PERSONclassperson{public:voidsetinfo(intn,char*strname,chars,char*strfrom);person();virtual~person();//虚析构函数virtualvoidshowinfo()=0;//纯虚函数protected:intid;charname[10];charsex;charfrom[20];};#endif19【例9.4】综合举例(P285)//person.cpp#includeperson.h#includeiostream.h#includestring.hperson::person(){setinfo(1,jetty,'M',china);}person::~person(){coutendldestructaperson;}voidperson::setinfo(intn,char*strname,chars,char*strfrom){id=n;strcpy(name,strname);sex=s;strcpy(from,strfrom);}20【例9.4】综合举例(P285)//undergraduate.h#includeperson.h#ifndef_UNDERGRADUATE#define_UNDERGRADUATEclassundergraduate:virtualpublicperson//虚继承{public:voidsetinfo(intn,char*strname,chars,char*strfrom,floatsc);undergraduate();~undergraduate();voidshowinfo();protected:floatscore;};#endif21【例9.4】综合举例(P285)//undergraduate.cpp#includeundergraduate.h#includeiostream.hundergraduate::undergraduate(){coutendlco
本文标题:C++面向对象程序设计第九章多态性与虚函数
链接地址:https://www.777doc.com/doc-3534798 .html