第5章 派生类与继承_第1页
第5章 派生类与继承_第2页
第5章 派生类与继承_第3页
第5章 派生类与继承_第4页
第5章 派生类与继承_第5页
已阅读5页,还剩80页未读 继续免费阅读

下载本文档

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

文档简介

第5章派生类与继承,内容提要:派生类的概念派生类的构造函数和析构函数多重继承虚函数与多态性,.,继承是面向对象程序设计的一个重要特性。它允许在既有类的基础上创建新的类,新类可以从一个或多个既有类中继承函数和数据,而且可以重新定义或加进新的数据和函数,从而形成类的层次或等级。既有类称为基类或父类,在它基础上建立的新类称为派生类或子类。,.,5.1派生类的概念,5.1.1为什么要继承现实世界中许多事物具有继承性,我们可以用层次分类的方法来描述它们之间的关系。例如:一个简单的汽车分类图,继承性也是程序设计中的一个非常有用的、有力的特性,它可以让程序员在既有类的基础上,通过增加少量代码或修改少量代码的方法得到新的类,从而较好的解决代码重用的问题。,.,派生类的概念,从以上类的声明可以看出,这两个类中的数据成员和成员函数有很多相同的地方。只要在person类的基础上再增加数据成员department和salary,再对print()成员函数稍加修改就可以定义出employee类。像这样定义两个类,代码重复太严重。为了提高代码的可重用性,就必须引入继承性,将employee类说明成person类的派生类,那些相同的成员在employee类中就不需要再定义了。,classpersonprivate:charname10;intage;charsex;public:voidprint();,classemployeeprivate:charname10;intage;charsex;chardepartment20;floatsalary;public:voidprint();,.,派生类的概念,5.1.2派生类的声明1.声明一个派生类的一般格式,/定义一个基类classpersonprivate:charname10;intage;charsex;public:/;/定义一个派生类classemployee:publicpersonprivate:chardepartment20;floatsalary;public:/;,class派生类名:派生方式基类名/派生类新增的数据成员和成员函数;,说明:派生类名就是要声明的新类名。基类名是一个已经定义的类。,.,派生类的概念,派生方式可以是关键字private或public。private指派生类从基类私有派生;public指派生类从基类公有派生。派生方式可以缺省,这时派生方式默认为private。,2.两种派生方式的特点无论是哪种派生方式,基类中的私有成员既不允许外部函数访问,也不允许派生类中的成员函数访问,但是可以通过基类提供的公有成员函数访问。公有派生与私有派生的不同点在于基类中的公有成员在派生类中的访问属性。公有派生时,基类中的所有公有成员在派生类中也都是公有的私有派生时,基类中的所有公有成员在派生类中都是私有的,.,派生类的概念,3.私有派生(1)私有派生类对基类成员的访问私有派生得到的派生类,对它基类的公有成员只能是私有继承,也就是说基类中的公有成员都只能成为私有派生类的私有成员,这些私有成员能够被派生类的成员函数访问,但是基类私有成员不能被派生类成员函数访问。,#includeclassbaseintx;public:voidsetx(intn)x=n;voidshowx()coutxendl;classderived:privatebaseinty;public:voidsetxy(intn,intm)setx(n);y=m;voidshowxy()coutxyendl;intmain()derivedobj;obj.setxy(10,20);obj.showxy();return0;,showx();coutyendl;,.,派生类的概念,(2)外部函数对私有派生类继承来的成员的访问私有派生时,基类的所有成员在派生类中都成为私有成员,外部函数不能访问。,#includeclassbaseintx;public:voidsetx(intn)x=n;voidshowx()coutxendl;classderived:privatebaseinty;public:voidsety(intm)y=m;voidshowxy()coutyendl;intmain()derivedobj;obj.setx(10);/非法obj.sety(20);obj.showx();/非法obj.showy();return0;,.,派生类的概念,3.公有派生公有派生时,基类中的私有成员在派生类中仍是私有成员,不允许外部函数和派生类中的成员函数直接访问,但是可以通过基类提供的公有成员函数访问。基类中的公有成员在派生类中仍是公有成员,外部函数和派生类中的成员函数可直接访问。,#includeclassbaseintx;public:voidsetx(intn)x=n;voidshowx()coutxendl;classderived:publicbaseinty;public:voidsety(intm)y=m;voidshowy()coutyendl;intmain()derivedobj;obj.setx(10);obj.sety(20);obj.showx();obj.showy();return0;,.,派生类的概念,说明:(1)派生类以公有派生的方式继承了基类,并不意味着派生类可以访问基类的私有成员。,#includeclassbaseintx;public:voidsetx(intn)x=n;voidshowx()coutxendl;classderived:publicbaseinty;public:voidsety(intm)y=m;voidshow_sum()coutx+yendl;/非法voidshowy()coutyendl;,.,派生类的概念,(2)在派生类中声明的名字支持基类中声明的同名的名字,即如果在派生类的成员函数中直接使用该名字的话,则表示使用派生类中声明的名字。对于派生类的对象的引用,也有同样的结论。,classXpublic:intf();classY:publicXpublic:intf();intg();voidY:g()f();/被调用的函数是Y:f(),而不是X:f()intmain()Yobj;obj.f();/被调用的函数是Y:f()obj.X:f();/被调用的函数是X:f(),.,派生类的概念,公有派生和私有派生的访问特性,基类成员,基类私有成员,基类公有成员,派生方式,private,public,private,public,派生类成员,外部函数,不可访问,不可访问,不可访问,不可访问,不可访问,可访问,可访问,可访问,.,派生类的概念,5.1.3保护成员保护成员:即protected成员,是C+提供的具有另一种访问属性的成员Protected说明符可以放在类声明的任何地方,通常将它放在私有成员声明之后,公有成员声明之前。类声明的一般格式:,class类名private:私有数据成员和成员函数protected:保护数据成员和成员函数public:公有数据成员和成员函数;,.,派生类的概念,保护成员可以被派生类的成员函数访问,但是对于外界是隐藏的,外部函数不能访问它。,#includeclasssampinta;protected:intb;public:intc;samp(intn,intm)a=n;b=m;intgeta()returna;intgetb()returnb;intmain()sampobj(20,30);obj.b=99;obj.c=50;coutobj.geta()endl;coutobj.getb()“”obj.cendl;return0;,/非法,.,派生类的概念,为了便于派生类的访问,可以将基类私有成员中需要提供给派生类访问的成员定义为保护成员。C+规定:基类的保护成员被派生类继承之后,若为公有派生,则基类中的保护成员在派生类中也为保护成员;若为私有派生,则基类中的保护成员在派生类中成为私有成员。,#includeclassbaseprotected:inta,b;public:voidsetab(intn,intm)a=n;b=m;classderive:publicbaseintc;public:voidsetc(intn)c=n;voidshowabc()couta“”b“”cendl;intmain()deriveobj;obj.setab(2,4);obj.setc(3);obj.showabc();return0;,.,派生类的概念,#includeclassbaseprotected:inta;public:voidseta(intsa)a=sa;classderive1:privatebaseprotected:intb;public:voidsetb(intsb)b=sb;,classderive2:publicderive1intc;public:voidsetc(intsc)c=sc;voidshow()cout“a=”aendl;cout“b=”bendl;cout“c=”cendl;voidmain()baseop1;op1.seta(1);derive1op2;op2.setb(2);derive2op3;op3.setc(3);op3.show();,.,派生类的概念,基类成员在派生类中的访问权限,派生方式,基类中的访问权限,派生类中的访问权限,public,private,public,private,public,private,protected,protected,private,private,private,private,public,protected,.,5.2派生类的构造函数和析构函数,派生类都有显式的或隐式的构造函数和析构函数。当创建一个派生类对象时,如何调用基类的构造函数对基类数据初始化,以及在撤销派生类对象时,又如何调用基类的析构函数来对基类对象的数据成员进行善后处理,这是本节要讨论的问题。,.,派生类的构造函数和析构函数,1.派生类构造函数和析构函数的执行顺序创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数;当撤销派生类对象时,则先执行派生类的析构函数,随后再执行基类的析构函数。,#includeclassbasepublic:base()cout“Constructingbaseclassn”;base()cout“Destructingbaseclassn”;classderive:publicbasepublic:derive()cout“Constructingderivedclassn”;derive()cout“Destructingderivedclassn”;intmain()deriveop;return0;,ConstructingbaseclassConstructingderivedclassDestructingderivedclassDestructingbaseclass,.,派生类的构造函数和析构函数,2.派生类构造函数和析构函数的构造规则当基类的构造函数没有参数,或没有显式定义构造函数时,派生类可以不向基类传递参数,甚至可以不定义构造函数。,#includeclassbasepublic:base()cout“Constructingbaseclassn”;base()cout“Destructingbaseclassn”;classderive:publicbasepublic:derive()cout“Constructingderivedclassn”;derive()cout“Destructingderivedclassn”;intmain()deriveop;return0;,.,派生类的构造函数和析构函数,派生类不能继承基类中的构造函数和析构函数。当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供把参数传递给基类构造函数的途径。C+中,派生类构造函数的一般格式为:,派生类构造函数名(参数表):基类构造函数名(参数表)/;,其中基类构造函数的参数,通常来源于派生类构造函数的参数表,也可以用常数值。,.,#includeclassbaseinti;public:base(intn)cout“Constructingbaseclassn”;i=n;base()cout“Destructingbaseclassn”;voidshowi()coutiendl;classderive:publicbaseintj;public:derive(intn,intm):base(m)cout“Constructingderivedclassn”;j=n;derive()cout“Destructingderivedclassn”;voidshowj()coutjendl;,voidmain()deriveobj(30,40);obj.showi();obj.showj();return0;,ConstructingbaseclassConstructingderivedclass4030DestructingderivedclassDestructingbaseclass,.,派生类的构造函数和析构函数,当派生类中含有对象成员时,其构造函数的一般形式为:,派生类构造函数名(参数表):基类构造函数名(参数表),对象成员名1(参数表),对象成员名n(参数表)/;,在定义派生类对象时,构造函数的执行顺序如下:基类的构造函数对象成员的构造函数派生类的构造函数撤销对象时,析构函数的调用顺序与构造函数的调用顺序正好相反,.,#includeclassbaseintx;public:base(intn)x=i;cout“Constructingbaseclassn”;base()cout“Destructingbaseclassn”;voidshow()cout“x=”xendl;classderive:publicbasebased;public:derive(inti):base(i),d(i)cout“Constructingderivedclassn”;derive()cout“Destructingderivedclassn”;,voidmain()deriveobj(5);obj.show();return0;,ConstructingbaseclassConstructingbaseclassConstructingderivedclassx=5DestructingderivedclassDestructingbaseclassDestructingbaseclass,.,派生类的构造函数和析构函数,说明:(1)当基类构造函数不带参数时,派生类不一定需要定义构造函数,然而当基类的构造函数哪怕只带有一个参数,它所有的派生类都必须定义构造函数,甚至所定义的派生类构造函数的函数体可能为空,仅仅起参数的传递作用。,classbaseinti;public:base(intn)cout“Constructingbaseclassn”;i=n;voidshowi()couti“n”;classderived:publicbaseintj;public:derived(intn):base(n)cout“Constructingderivedclassn”;j=0;voidshowj()coutjendl;,.,派生类的构造函数和析构函数,(2)若基类使用缺省构造函数或不带参数的构造函数,则在派生类中定义构造函数时可略去“:基类构造函数名(参数表)”;此时若派生类也不需要构造函数,则可不定义构造函数。(3)如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造,依次上溯。(4)由于析构函数是不带参数的,在派生类中是否要定义析构函数与它所属的基类无关,故基类的析构函数不会因为派生类没有析构函数而得不到执行,它们各自是独立的。,.,5.3多继承,单继承(单基派生):一个派生类只有一个直接基类。多继承(多基派生):一个派生类具有两个或两个以上的直接基类。1.多继承的声明声明的一般形式:,class派生类名:派生方式1基类名1,派生方式n基类名n/派生类新增的数据成员和成员函数;,说明:冒号后面的部分称基类表;各基类之间用逗号分隔;其中派生方式规定了按什么方式继承:private或public,缺省的派生方式是private。,.,多继承,classz:publicx,y/;,说明:多继承中,公有派生和私有派生对于基类成员在派生类中的可访问性与单继承的规则相同。,类z公有继承了类x,私有继承了类y,classz:x,publicy/;,类z私有继承了类x,公有继承了类y,classz:publicx,publicy/;,类z公有继承了类x和类y,.,#includeclassXinta;public:voidsetX(intx)a=x;voidshowX()cout“a=”aendl;classYintb;public:voidsetY(intx)b=x;voidshowY()cout“b=”bendl;,classZ:publicX,privateYintc;public:voidsetZ(intx,inty)c=x;setY(y);voidshowZ()showY();cout“c=”cendl;voidmain()Zobj;obj.setX(3);obj.showX();obj.setY(4);obj.showY();obj.setZ(6,8);obj.showZ();,多继承,/错误,/错误,A=3B=6C=8,.,多继承,说明:对基类成员的访问必须是无二义的。,classXpublic:intf();classYpublic:intf();intg();classZ:publicX,publicYpublic:intg();inth();,假如定义类Z的对象obj:Zobj;则以下对函数f()的访问是二义的:obj.f();使用成员名限定可以消除二义性,例如:obj.X:f();obj.Y:f();,.,多继承,2.多继承的构造函数与析构函数(1)多继承构造函数定义的一般形式:,派生类构造函数名(参数表):基类1构造函数名(参数表),基类2构造函数名(参数表),基类n构造函数名(参数表)/;,.,classHardprotected:charbodyname20;public:Hard(char*bdna);/;classSoftprotected:charos10;charLang15;public:Soft(char*o,char*lg);/;,classSystem:publicHard,publicSoftprivate:charowner10;public:System(char*ow,char*bn,char*o,char*lg):Hard(bn),Soft(o,lg);/;,多继承,说明:在定义派生类system的构造函数时,缀上了Hard和Soft的构造函数。,.,classwindow/public:window(inttop,intleft,intbottom,intright);window();/;classscrollbar/public:scrollbar(inttop,intleft,intbottom,intright);scrollbar();/;classscrollbarwind:window,scrollbar/public:scrollbarwind(inttop,intleft,intbottom,intright);scrollbarwind();/;,多继承,.,scrollbarwind:scrollbarwind(inttop,intleft,intbottom,intright):window(top,left,bottom,right),scrollbar(top,right-20,bottom,right)/,多继承,说明:在定义派生类scrollbarwind的构造函数时,也缀上了基类window和scrollbar的构造函数。,.,#includeclassXinta;public:X(intsa)a=sa;intgetX()returna;classYintb;public:Y(intsb)b=sb;intgetY()returnb;,classZ:publicX,privateYintc;public:Z(intsa,intsb,intsc):X(sa),Y(sb)c=sc;intgetZ()returnc;intgetY()returnY:getY();intmain()Zobj(2,4,6);intma=obj.getX();cout“a=”maendl;intmb=obj.getY();cout“b=”mbendl;intmc=obj.getZ();cout“c=”mcendl;return0;,多继承,a=2b=4c=6,.,多继承,(2)多继承的构造函数的执行顺序多继承的构造函数的执行顺序与单继承构造函数的执行顺序相同,也是遵循先执行基类的构造函数,再执行对象成员的构造函数,最后执行派生类构造函数的原则。在多个基类之间,严格按照派生类的声明时从左到右的顺序来排列先后。析构函数的执行顺序刚好与构造函数的执行顺序相反。,.,多继承,3.虚基类(1)虚基类的引入,#includeclassbaseprotected:inta;public:base()a=5;classbase1:publicbasepublic:base1()coutbase1a=aendl;,classbase2:publicbasepublic:base2()coutbase2a=aendl;classderived:publicbase1,publicbase2public:derived()coutderiveda=aendl;intmain()derivedobj;return0;,.,多继承,从图中可以看出,虽然base1和base2是从同一个基类base派生而来的,但它们所对应的是基类base的不同拷贝。类derived是base1和base2的派生类,因此类base是类derived的间接基类,它有两个拷贝与类derived相对应,一个是base1派生路径上的拷贝,另一个是base2派生路径上的拷贝。当类derived要访问这个间接基类base时,必须指定要访问的是哪个路径上的base拷贝。,类的层次图,.,多继承,classderived:publicbase1,publicbase2public:derived()coutderiveda=aendl;,base1:a,解决方法:指定访问路径,引入虚基类,即类base只存在一个拷贝,则对a的引用就不会产生二义性。,.,多继承,(2)虚基类的概念C+中,如果想使公共的基类只产生一个拷贝,则可以将这个基类说明为虚基类。使用方法:从类base派生新类时,使用关键字virtual将类base说明为虚基类。,#includeclassbaseprotected:inta;public:base()a=5;classbase1:virtualpublicbasepublic:base1()coutbase1a=aendl;,classbase2:virtualpublicbasepublic:base2()coutbase2a=aendl;classderived:publicbase1,publicbase2public:derived()coutderiveda=aendl;intmain()derivedobj;return0;,.,多继承,说明:,classLpublic:intnext;classA:virtualpublicL;classB:virtualpublicL;classC:publicA,publicBpublic:voidf()next=0;,对于类C而言,L类是B类的虚基类,而是类A的真基类;但对于类B而言,L类还是B类的真基类。如果派生时,A,B的顺序变了则对于类C而言,L类是A类的虚基类,而是类B的真基类。,publicB,publicA,说明虚基类时,virtual和public的顺序可以交换。,publicvirtualL,publicvirtualL在,.,多继承,一个派生类的对象的地址可以直接赋给虚基类的指针,例如:Cobj;L*ptr=将产生编译错误。,.,多继承,(3)虚基类对象的初始化虚基类的初始化与一般的多重继承的初始化在语法上是一样的,但构造函数的调用顺序不同。虚基类构造函数的调用顺序:若同一层次中包含多个虚基类,这些虚基类的构造函数按对它们说明的先后次序调用;若虚基类由非虚基类派生而来,则仍然先调用基类构造函数,再调用派生类的构造函数;若同一层次中同时包含虚基类和非虚基类,应先调用虚基类的构造函数,再调用非虚基类的构造函数,最后调用派生类构造函数。,.,多继承,ClassX:publicY,virtualpublicZ/;Xone;,定义类X的对象one时,将产生如下的调用次序:Z();Y();X();说明:Z是X的虚基类,故先调用Z的构造函数,再调用Y的构造函数,最后才调用派生类X自己的构造函数。,.,多继承,#includeiostream.hclassbasepublic:base()coutBaseendl;classbase2public:base2()coutBase2endl;classlevel1:publicbase2,virtualpublicbasepublic:level1()coutlevel1endl;classlevel2:publicbase2,virtualpublicbasepublic:level2()coutlevel2endl;classtoplevel:publiclevel1,virtualpubliclevel2public:toplevel()couttoplevelendl;,toplevelview;voidmain();,BaseBase2level2Base2level1toplevel,.,多继承,分析:表示类之间继承关系的示意图,.,多继承,classbase;classbase2;classlevel1:publicbase2,virtualpublicbase;classlevel2:publicbase2,virtualpublicbase;classtoplevel:virtualpubliclevel1,publiclevel2;toplevelview;,base()base2()level1()base2()level2()toplevel(),.,多继承,classB;classX:virtualpublicB;classY:virtualpublicB;classZ:publicB;classAA:publicX,publicY,publicZ;,B()X()Y()B()Z()AA(),这里AA具有两个B类的子对象:Z的B和x与Y共享的虚拟的B。,.,多继承,classVpublic:intv;classApublic:inta;classB:publicA,virtualpublicV;classC:publicA,VirtualpublicV;classD:publicB,publicCpublic:voidf();voidD:f()v+;a+;,B():V()A()B()C():A()C()D():D(),在D中仅仅一个v,错误,具有二义性,在D中有两个a,.,5.4虚函数与多态性,5.4.1虚函数对于普通成员函数的重载,可表达为下面的方式:在同一个类中重载在不同类中重载基类的成员函数在派生类中重载重载函数的访问是在编译时区分的,有以下三种方法:根据参数的特征加以区分,例如:Show(int,char)与Show(char*,float)不是同一函数,编译能区分。使用“:”加以区分,例如:Circle:Show有别于Point:Show根据类对象加以区分。ACircle.Show()调用Circle:Show()APoint.Show()调用Point:Show()这里ACircle和APoint分别是Circle和Point的对象。,.,#includeclassApublic:voidfun()cout“InA”endl;classB:publicApublic:voidfun()cout“InB”endl;classC:publicBpublic:voidfun()cout“InC”endl;,voidmain()CCobj;Cobj.fun();Cobj.B:fun();Cobj.A:fun();A,.,虚函数与多态性,虚函数是重载的另一种表现形式。1、基类对象的指针指向派生类对象指向基类和派生类的指针变量是相关的,假设B_class是基类,D_class是从B_class公有派生出来的派生类,则任何被说明为指向B_class的指针也可以指向D_class。,B_class*p;B_classB_ob;D_classD_ob;p=,利用p,可以访问从基类B_class继承的成员,但D_class自己定义的成员,p不能访问。,.,#include#includeclassB_classcharname80;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classD_class:publicB_classcharphone_num80;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numshow_phone();,.,#includeclassBaseprotected:intx;public:Base(inta)x=a;voidwho()cout“base”x“n”;classFirst_d:publicBasepublic:First_d(inta):Base(a)voidwho()cout“Firstderivation”x“n”;classsecond_d:publicBasepublic:second_d(inta):Base(a)voidwho()cout“Secondderivation”who()能调用不同类中who()版本,这样就可以用一个界面p-who()访问多个实现版本:Base中的who(),First_d中的who(),以及Second_d中的who(),这在编程时非常有用。实际上,这表达了一种动态的性质,函数调用p-who()依赖于运行时p所指向的对象。虚函数提供的就是这种解释机制。,.,虚函数与多态性,2、虚函数的定义虚函数是在基类中被冠以virtual的成员函数,它提供了一种接口界面。虚函数可以在一个或多个派生类中被重新定义。虚函数在派生类中重新定义时,要求其函数原型,包括返回类型、函数名、参数个数、参数类型的顺序必须完全相同。,.,#includeclassBaseprotected:intx;public:Base(inta)x=a;virtualvoidwho()cout“base”x“n”;classFirst_d:publicBasepublic:First_d(inta):Base(a)voidwho()cout“Firstderivation”x“n”;classsecond_d:publicBasepublic:second_d(inta):Base(a)voidwho()cout“Secondderivation”xwho(),虚函数与多态性,.,基类函数f具有虚特性的条件是:(1)在基类中,将该函数说明为virtual函数。(2)定义基类的公有派生类。(3)在基类的公有派生类中原型一致地重载该虚函数。(4)定义指向基类的指针变量,它指向基类的公有派生类的对象(或定义指向基类的引用,它引用基类的公有派生类的对象)。,虚函数与多态性,.,voidmain()derivedd;base*bp=,classbasepublic:virtualvoidvf1();virtualvoidvf2();virtualvoidvf3();voidf();classderived:publicbasepublic:voidvf1();voidvf2(int);charvf3();voidf();;,错误,仅返回类型不同,具有虚特性,一般函数重载,参数不同,虚特性丢失,一般的函数重载,非虚函数的重载,.,#includeclassfigureprotected:doublex,y;public:voidset_dim(doublei,doublej=0)x=i;y=j;virtualvoidshow_area()cout“Noareacomputationdefined”;cout“forthisclass.n”;classtriangle:publicfigurepublic:voidshow_area()cout“Trianglewithhigh”;coutx“andbase”y;cout“hasanareaof”;coutx*0.5*y“n”;classsquare:publicfigurepublic:voidshow_area()cout“Squarewithdimension”;coutx“*”y;cout“hasanareaof”;coutx*yshow_area();,.,程序输出:Trianglewithhigh10andbase5hasanareaof25.0Squarewithdimension10*5hasanareaof50.0Circlewithradius9hasanareaof254.34,.,虚函数与多态性,3、使用成员名限定可以强制使用静态联编,#includeclassApublic:virtualvoidfun()coutInAend1;classB:publicApublic:voidfun()coutInBend1;classC:publicBpublic:voidfun()coutInCend1;,voidmain()CCobj;Cobj.fun();Cobj.B:fun();Cobj.A:fun();A*Aref=,InCInBInAInCInCInB,.,虚函数与多态性,4、在成员函数中调用虚函数在一个基类或派生类的成员函数中,可以直接调用等级中的虚函数。此时,需要根据成员函数中this指针和它所指向的对象来判断调用的是哪个函数。,#includeclassApublic:virtualvoidfun1()coutA1-2endl;fun2();virtualvoidfun2()coutA2-3endl;fun3();virtualvoidfun3()coutA3-4endl;fun4();virtualvoidfun4()coutA4-5endl;fun5();virtualvoidfun5()coutAendendl;classB:publicApublic:voidfun1()coutB1-2endl;fun2();voidfun2()coutB2-3endl;fun3();voidfun3()coutB3-4endl;fun4();voidfun4()coutB4-5endl;fun5();voidfun5()coutBendfun1();deleteApointer1;deleteApointer2;,A1-2A2-3A3-4A4-5AendB1-2B2-3B3-4B4-5Bend,.,虚函数与多态性,voidmain()A*Apointer=newB;Apointer-fun1();deleteApointer;,A1-2B2-3B3-4B4-5Bend,#includeclassApublic:voidfun1()coutA1-2endl;fun2();virtualvoidfun2()coutA2-3endl;fun3();virtualvoidfun3()coutA3-4endl;fun4();virtualvoidfun4()coutA4-5endl;fun5();virtualvoidfun5()coutAendendl;classB:publicApublic:voidfun1()coutB1-2endl;fun2();voidfun2()coutB2-3endl;fun3();voidfun3()coutB3-4endl;fun4();voidfun4()coutB4-5endl;fun5();voidfun5()coutBendfun1();deleteApointer;,A1-2A2-3B3-4B4-5Aend,#includeclassApublic:virtualvoidfun1()coutA1-2endl;fun2();virtualvoidfun2()coutA2-3endl;fun3();virtualvoidfun3()coutA3-4endl;fun4();virtualvoidfun4()coutA4-5endl;fun5();virtualvoidfun5()coutAendendl;classB:publicApublic:voidfun3()coutB3-4endl;fun4();voidfun4()coutB4-5endl;fun5();,.,虚函数与多态性,5、在构造函数和析构函数中调用虚函数在构造函数和析构函数中调用虚函数时,采用静态联编。即它们所调用的虚函数是自己的类或者它的基类中的虚函数,但不是任何在派生类中定义的虚函数。,#includeclassApublic:A()coutAisCreatingendl;virtualvoidfun1()coutAfun1endl;virtualvoidfun2()coutAfun2endl;A()coutAisDestroyendl;classB:publicApublic:B()coutBisCreatingendl;fun1();voidfun()fun1();B()coutBisdestroyendl;fun2();classC:publicBpublic:C()coutCisCreatingendl;voidfun1()coutCfun1endl;virtualvoidfun2()coutCfun2endl;C()coutCisDestroyendl;fun2();,voidmain()CCobj;Cobj.fun();,AisCreatingBisCreatingAfun1CisCreatingCfun1CisdestroyCfun2BisdestroyAfun2Aisd

温馨提示

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

评论

0/150

提交评论