版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、会计学1C语言试题语言试题(sht)、学习、考试大全、学习、考试大全第一页,共57页。13.1 函数重载函数重载 13.2 运算符重载运算符重载 13.3 静态静态(jngti)联编联编 13.4 动态联编和虚函数动态联编和虚函数 13.5 纯虚函数和抽象类纯虚函数和抽象类 第1页/共57页第二页,共57页。第第 13 章章 多态性多态性 多态性是实现多态性是实现(shxin) OOP 的关键技术之一。的关键技术之一。 在在C+中,多态性分为两种:中,多态性分为两种: 静态静态(jngti)多态多态 动态多态动态多态 函数重载和运算符重载属于静态多态。函数重载和运算符重载属于静态多态。函数重载
2、:相同函数名可以函数重载:相同函数名可以(ky)完成不同功能。完成不同功能。运算符重载:相同运算符完成不同功能。运算符重载:相同运算符完成不同功能。 动态多态动态多态是指:程序执行过程中确定的关系,是指:程序执行过程中确定的关系, 如动态确定函数的调用关系。如动态确定函数的调用关系。 运行时的多态(动态多态)运行时的多态(动态多态) 是通过类的继承和虚函数来实现的。是通过类的继承和虚函数来实现的。第2页/共57页第三页,共57页。13.1 函数函数(hnsh)重载重载 参见参见5.6节(略)节(略) 13.2 重载重载(zhn zi)运算符运算符 C+中所有的运算符都已预先中所有的运算符都已预
3、先(yxin)定义了用法及意义。定义了用法及意义。 如:如:+ * / = 等,适用于已有的数据类型。等,适用于已有的数据类型。 已定义的已定义的用法及意义是不允许用户改变的。用法及意义是不允许用户改变的。 如果用户定义了新的数据类型,希望已定义的运算符如果用户定义了新的数据类型,希望已定义的运算符 能适应新的数据类型,能适应新的数据类型, 如如: 前述前述 Complex 类的加法运算类的加法运算Complex c1, c2, c3;c3 = add(c1, c2); /以前通过函数实现加法运算以前通过函数实现加法运算c2.add(c3); / 或或通过成员函数实现通过成员函数实现c3 =
4、c1 + c2; /能否直观地写成这样?能否直观地写成这样?能能 ! 运算符的重载可以达到此目的。运算符的重载可以达到此目的。第3页/共57页第四页,共57页。 允许允许(ynx)重载重载 和和 不允许不允许(ynx)重载的运算符见重载的运算符见13-1和和13-2表。表。13.2.1 运算符重载运算符重载(zhn zi)的几点说的几点说明明重载运算符的限制重载运算符的限制(1)只能)只能(zh nn)对已有运算符重载,不可臆造新的运算符。对已有运算符重载,不可臆造新的运算符。(2)不允许改变运算符的优先级和结合性。)不允许改变运算符的优先级和结合性。(3)不允许改变运算符的语法结构,)不允许
5、改变运算符的语法结构, 如二元运算符只能如二元运算符只能(zh nn)重载成二元运算符,重载成二元运算符, 一元运算符只能一元运算符只能(zh nn)重载成一元运算符。重载成一元运算符。第4页/共57页第五页,共57页。1.重载为类的成员重载为类的成员(chngyun)函数函数 在类内定义在类内定义(dngy)运算符重载函数的格式为:运算符重载函数的格式为: operator ( ) 以以 operator 为关键字,编译器可以很容易将为关键字,编译器可以很容易将运算符重载函数与其他成员运算符重载函数与其他成员(chngyun)函数区别开来。函数区别开来。例例13.2 实现复数类的实现复数类的
6、“+”,“-”等重载运算等重载运算 关键部分见下页关键部分见下页13.2.2 运算符重载的两种方式运算符重载的两种方式在类外定义运算符重载函数的格式为:在类外定义运算符重载函数的格式为: :operator ( )特殊的成员函数名特殊的成员函数名第5页/共57页第六页,共57页。class Complex float Real, Image;public: . Complex operator +(const Complex &c); Complex operator +(double); Complex operator-(const Complex &c); Complex
7、 operator-(double); Complex operator-(void); . ;Complex Complex:operator +(const Complex &c) return Complex (Real+c.Real, Image+c.Image); Complex Complex:operator +(double r) return Complex(Real+r, Image); Complex Complex:operator-(void) return Complex(-Real, -Image); 第6页/共57页第七页,共57页。void main(
8、 ) Complex c1(2, 3), c2(4, -2), c3; c3 = c1+c2 ; c3 = c1+5 ; c3 = - c1; 编译器将编译器将 c1+c2 解释解释(jish)为:为:c1.operator+(c2)将将 c1+5 解释解释(jish)为:为:c1.operator+(5)第第1个运算量是对象个运算量是对象(duxing),第,第2个运算量是参数。个运算量是参数。阅读教材上程序全文阅读教材上程序全文(讲解略)(讲解略)将将 - c1 解释为:解释为:c1.operator( ) 当用成员函数实现运算符的重载时,重载函数的当用成员函数实现运算符的重载时,重载函数
9、的 参数个数只能是参数个数只能是 0 个或个或 1 个。分别实现:一元、二元个。分别实现:一元、二元 运算符的重载。运算符的重载。第7页/共57页第八页,共57页。2.重载重载(zhn zi)为友元函数为友元函数 例例13.3 用友元函数实现用友元函数实现(shxin)复数类的复数类的“+”和和“” 重载运算重载运算 关键部分见下页关键部分见下页在在类内类内定义友元重载函数的格式为:定义友元重载函数的格式为:friend operator ( )在在类外类外定义友元重载函数的格式为:定义友元重载函数的格式为: operator ( )第8页/共57页第九页,共57页。class Complex
10、 float Real, Image;public: . friend Complex operator +(const Complex &c1, const Complex &c2); friend Complex operator(const Complex &c); . ;Complex operator +(const Complex &c1, const Complex &c2)/二元运算二元运算(yn sun) Complex t; t.Real=c1.Real+c2.Real; t.Image=c1.Image+c2.Image; retu
11、rn t;Complex operator(const Complex c) /一元运算一元运算(yn sun) return Complex(c.Real, c.Image) ;不是类的成员函数不是类的成员函数在在 main( )函数函数(hnsh)中中,若有若有 Complex c1,c2; 则编译器将则编译器将 c1+c2 解释为:解释为:operator+(c1, c2)将将 c1 解释解释(jish)为:为:operator(c1)第9页/共57页第十页,共57页。阅读教材阅读教材(jioci)上程序全文(讲解略)上程序全文(讲解略) 当用友元函数实现当用友元函数实现(shxin)运
12、算符的重载时,重载函数的运算符的重载时,重载函数的 参数个数只能是参数个数只能是1 个或个或 2 个。个。 分别实现分别实现(shxin):一元运算符重载、二元运算符重载:一元运算符重载、二元运算符重载3.两种重载方式两种重载方式(fngsh)的比较的比较 成员实现:成员实现:将将 c1+c2 解释为:解释为:c1.operator +(c2)友元实现:友元实现:将将 c1+c2 解释为:解释为:operator +(c1, c2)成员实现:成员实现:将将 c1+5.6 解释为:解释为:c1.operator +(5.6)友元实现:友元实现:将将 c1+5.6 解释为:解释为:operator
13、 +(c1, 5.6)成员实现:成员实现:将将 5.6 + c1解释为:解释为: 5.6.operator + (c1) 友元实现:友元实现:将将 5.6 + c1解释为:解释为:operator + ( 5.6, c1)第10页/共57页第十一页,共57页。因此因此(ync):对一般的二元运算符重载为友元函数比重载为成员函数对一般的二元运算符重载为友元函数比重载为成员函数更优越。更优越。但是对于赋值运算符,将其重载为成员函数较好,因为但是对于赋值运算符,将其重载为成员函数较好,因为赋值运算符是一个二元运算符,赋值运算符是一个二元运算符,其语法格式为其语法格式为 =,第一个运算量必须是对象(变
14、量也是对象),通过对象第一个运算量必须是对象(变量也是对象),通过对象调用成员函数比较自然。调用成员函数比较自然。若重载为友元,则可能会出现若重载为友元,则可能会出现5.6=c这样的表达式,与这样的表达式,与赋值表达式的语义不一致。赋值表达式的语义不一致。 第11页/共57页第十二页,共57页。定义友元的目的是在友元函数中直接访问类的私有成员,定义友元的目的是在友元函数中直接访问类的私有成员,实际上,也可以通过公有函数接口访问类的私有成员,实际上,也可以通过公有函数接口访问类的私有成员,所以实现所以实现(shxin)运算符重载,可以即不用成员函数,运算符重载,可以即不用成员函数,也不用友元函数
15、。也不用友元函数。class Complex float Real, Image;public: Complex(double r=0, double i=0) Real=r; Image=i; void SetReal(double Real) Complex:Real = Real; void SetImage(double Image) Complex:Image = Image; double GetReal( ) return(Real); double GetImage( ) return(Image); ; 4.使用使用(shyng)非成员、非友元实现运算符的重载非成员、非友元实
16、现运算符的重载例例13.4:第12页/共57页第十三页,共57页。Complex operator +(Complex &c1, Complex &c2) /二元运算二元运算(yn sun) Complex t; t.SetReal( c1.GetReal( )+c2.GetReal( ) ); t.SetImage( c1.GetImage( )+c2.GetImage( ) ); return t; void main( )Complex c1(2, 3), c2(4, 8), c3;c3 = c1+c2;c3.Show( );编译器将编译器将 c1+c2 解释解释(jis
17、h)为:为:operator +(c1, c2)第13页/共57页第十四页,共57页。对于对于(duy)Complex类,如有类,如有Complex c1(2, 3), c2; 则自动将则自动将 c2=c1; 处理成:处理成: c2.Real = c1.Real; c2.Image = c1. Image; 一般不会出现问题。一般不会出现问题。 5. 何时必须何时必须(bx)重载重载 = 和和 += 运算符?运算符? 相同类型的对象之间是可以直接赋值的,相同类型的对象之间是可以直接赋值的,C+将赋值将赋值处理成两个对象的各个处理成两个对象的各个(gg)成员直接赋值。两个对成员直接赋值。两个对象
18、的对应数据成员逐一赋值。象的对应数据成员逐一赋值。例例13.5 在类中,用字符数组实现字符串。在类中,用字符数组实现字符串。 见见 “第第13章章 多态性多态性(例子例子).doc”第14页/共57页第十五页,共57页。Num数组数组Name数组数组Score整数整数stud1存储空间存储空间Num数组数组Name数组数组Score整数整数stud2存储空间存储空间程序程序(chngx)中中A行使用赋值运算符进行对象整体赋值,行使用赋值运算符进行对象整体赋值, C+将其处理成各个成员逐一赋值将其处理成各个成员逐一赋值,如下图所示:如下图所示: :C+默认默认(mrn)的处理是:的处理是:str
19、cpy(stud2.Num, stud1.Num); strcpy(stud2.Name, stud1.Name); stud2.Score = stud1.Score; 。 但是如果对象的成员中有成员指向但是如果对象的成员中有成员指向(zh xin)动态分配的动态分配的 数据空间就会出现问题。数据空间就会出现问题。 第15页/共57页第十六页,共57页。例例13.6 在类中,用指针实现字符串,在类中,用指针实现字符串, 即字符串的空间是动态分配的。即字符串的空间是动态分配的。 class Studentchar *Nump; /学号,注意学号,注意(zh y):用指针实现:用指针实现char
20、 *Namep; /姓名,注意姓名,注意(zh y):用指针实现:用指针实现int Score; /成绩成绩public: Student(char *nump=NULL, char *namep=NULL, int score=0) if(nump) /构造函数构造函数 Nump = new charstrlen(nump)+1;strcpy(Nump, nump); /动态分配存储空间动态分配存储空间 else Nump=NULL; if(namep) Score=score;第16页/共57页第十七页,共57页。Student( ) / 析构函数,释放指针析构函数,释放指针(zhzhn)
21、指向的空间指向的空间 if(Nump)delete Nump;if(Namep)delete Namep;void Show( ) if(Nump & Namep) coutNum=NumptName=NameptScore=Scoreendl;第17页/共57页第十八页,共57页。void main( )Student stud1(01201, Mary, 88), stud2;stud2=stud1; /Astud1.Show( );stud2.Show( );cout.flush( ); /BNump指针指针Namep指针指针Score整数整数stud2存储空间存储空间Nump指
22、针指针Namep指针指针Score整数整数stud1存储空间存储空间01201Mary首先撤消对象首先撤消对象stud2,然后撤消对象,然后撤消对象stud1 ,出问题,出问题(wnt)!同一对象被撤销两次。同一对象被撤销两次。 编译器将编译器将A行处理行处理(chl)成:成:第18页/共57页第十九页,共57页。解决办法,在类中增加赋值解决办法,在类中增加赋值 = 重载重载(zhn zi)函数:函数:Student & operator=(const Student &stud) / 返回值为对象自身的引用返回值为对象自身的引用(ynyng) if(Nump)delete N
23、ump; / C 释放对象自身的原串空间释放对象自身的原串空间 if(Namep)delete Namep; / D 释放对象自身的原串空间释放对象自身的原串空间 if(stud.Nump) / 根据赋值对象的空间大小给被赋值对象分配空间根据赋值对象的空间大小给被赋值对象分配空间 Nump = new charstrlen(stud.Nump)+1;strcpy(Nump, stud.Nump); else Nump=NULL; if(stud.Namep) / 根据赋值对象的空间大小给被赋值对象分配空间根据赋值对象的空间大小给被赋值对象分配空间 Namep = new charstrlen(
24、stud.Namep)+1;strcpy(Namep, stud.Namep); else Namep=NULL; Score=stud.Score; return *this; / *this是对象自身是对象自身 第19页/共57页第二十页,共57页。Nump指针指针Namep指针指针Score整数整数stud2存储空间存储空间Nump指针指针Namep指针指针Score整数整数stud1存储空间存储空间01201Mary01201Mary在赋值时,为目的对象在赋值时,为目的对象(duxing)的指针重新分配指向的字的指针重新分配指向的字符串空间。符串空间。增加赋值增加赋值 = 重载函数后,
25、对象重载函数后,对象(duxing)赋值后的存储空赋值后的存储空间如下:间如下:这样,程序结束这样,程序结束(jish)时,分别撤销两个对象,程序正时,分别撤销两个对象,程序正确运行!确运行!第20页/共57页第二十一页,共57页。6对于对于+=(或(或=)运算符,重载函数)运算符,重载函数(hnsh)的返回值为的返回值为void类型或本类类型对象的区别类型或本类类型对象的区别 例例13.7 见见 “第第13章章 多态性多态性(例子例子(l zi).doc”若重载若重载(zhn zi)为返回为返回void类型,则本类对象不类型,则本类对象不可连续赋值。可连续赋值。若重载若重载(zhn zi)为
26、返回本类类型,则本类对象可为返回本类类型,则本类对象可以连续赋值。以连续赋值。第21页/共57页第二十二页,共57页。7对于对于+=(或(或=)运算符,返回本类对象与返回本类)运算符,返回本类对象与返回本类对象的引用对象的引用(ynyng)的区别的区别 比较比较(bjio)下面两例,先看第一个例子:下面两例,先看第一个例子: Complex Complex :operator+=(const Complex &c) Real+=c.Real; Image+=c.Image; return *this; 此函数的返回值为本类对象,此函数的返回值为本类对象,C+的处理是:用返回的对的处理是
27、:用返回的对象值象值*this初始化内存临时对象(调用拷贝构造函数),初始化内存临时对象(调用拷贝构造函数),从本函数返回后,用内存临时对象作为调用函数的结果从本函数返回后,用内存临时对象作为调用函数的结果。 第22页/共57页第二十三页,共57页。再看第二个例子:再看第二个例子:Complex Complex :operator+=(const Complex &c) Real+=c.Real; Image+=c.Image; Complex temp = *this ;return temp;C+的处理是:调用拷贝构造函数,用返回的对象值的处理是:调用拷贝构造函数,用返回的对象值t
28、emp初始化内存临时初始化内存临时(ln sh)对象,内存临时对象,内存临时(ln sh)对对象作为调用函数的结果。象作为调用函数的结果。 第23页/共57页第二十四页,共57页。从上面两个小例子可以看出,若重载函数返回对象值,从上面两个小例子可以看出,若重载函数返回对象值,则返回则返回*this和返回和返回temp均可。均可。但要注意,因为返回对象值时需要调用但要注意,因为返回对象值时需要调用(dioyng)拷贝拷贝构造函数初始化内存临时对象,因此若对象有动态分配构造函数初始化内存临时对象,因此若对象有动态分配的存储空间,就必须定义拷贝构造函数。的存储空间,就必须定义拷贝构造函数。 第24页
29、/共57页第二十五页,共57页。第三个例子第三个例子(l zi): Complex & Complex :operator+=(const Complex &c) Real+=c.Real; Image+=c.Image;return *this; 本例的返回值为本类对象的引用,不需初始化内存临时对象本例的返回值为本类对象的引用,不需初始化内存临时对象,返回值是对象自身,即,返回值是对象自身,即*this。因为不需要初始化内存临。因为不需要初始化内存临时对象,效率较高,所以像时对象,效率较高,所以像 +=、= 等改变对象值的重载函等改变对象值的重载函数最好返回对象的引用。数最好
30、返回对象的引用。 第25页/共57页第二十六页,共57页。第四个例子:第四个例子:Complex & Complex :operator+=(const Complex &c) Real+=c.Real; Image += c.Image; Complex temp = *this ;return temp;此时,出现问题。因为返回的是对象的引用(即对象自此时,出现问题。因为返回的是对象的引用(即对象自身,不借助于内存临时对象),系统要求在执行流程身,不借助于内存临时对象),系统要求在执行流程(lichng)返回到调用处时,返回值是存在的。但是本例返回到调用处时,返回值是存在的
31、。但是本例返回值是函数内部的局部对象返回值是函数内部的局部对象temp,而局部对象在函数,而局部对象在函数返回前,其空间是被撤消的。返回前,其空间是被撤消的。第26页/共57页第二十七页,共57页。结论:结论: 返回本类对象时,可以用对象自身和局部对象做为返回值返回本类对象时,可以用对象自身和局部对象做为返回值(有时需要定义拷贝(有时需要定义拷贝(kobi)构造函数)。构造函数)。 返回对象的引用时,不能用局部对象做为返回值。返回对象的引用时,不能用局部对象做为返回值。例例13.8对于字符串类,重载对于字符串类,重载 = 运算符,返回对象自身的引运算符,返回对象自身的引用。就本例而言,可以用。
32、就本例而言,可以(ky)不定义拷贝构造函数,程序能不定义拷贝构造函数,程序能正确运行。正确运行。 见见 “第第13章章 多态性多态性(例子例子).doc”第27页/共57页第二十八页,共57页。8.调用拷贝调用拷贝(kobi)构造函数构造函数 和和 调用赋值运算符重载函数的时机调用赋值运算符重载函数的时机 class Complexdouble Real, Image;public:Complex(double r=0, double i=0) / 构造函数构造函数 Real=r; Image=i; Complex(Complex &c) / 拷贝拷贝(kobi)构造函数构造函数 Re
33、al=c.Real; Image=c.Image; coutCall copy Real Imagen; ;void main( )Complex c1(2, 3), c2(4, -2);Complex c3=c1; c1=c2; 程序程序(chngx)的运行结果是?的运行结果是?调用了拷贝构造函数调用了拷贝构造函数未调用拷贝构造函数未调用拷贝构造函数Call copy 2 3v只有在产生新对象时,调用构造函数。只有在产生新对象时,调用构造函数。v用已有对象初始化新产生的对象时,用已有对象初始化新产生的对象时, 调用拷贝构造函数。调用拷贝构造函数。v赋值运算赋值运算 = , 不调用拷贝构造函数
34、。不调用拷贝构造函数。第28页/共57页第二十九页,共57页。13.2.3 类型转换函数将本类对象类型转换函数将本类对象(duxing)转换成其转换成其他类对象他类对象(duxing)例例: Complex c(3, 2); double x=6.2;如果有如果有: c=x; /类型不一致类型不一致(yzh) 或或: x=c; /类型不一致类型不一致(yzh)则系统自动处理为则系统自动处理为: c = Complex(x); /需作类型转换需作类型转换 x = double(c); /需作类型转换需作类型转换对于,通过以前所学的对于,通过以前所学的构造函数构造函数实现类型转换,实现类型转换,
35、将其他类型的数据转换成本类数据将其他类型的数据转换成本类数据。对于,使用本节将介绍的类型转换对于,使用本节将介绍的类型转换运算符重载函数运算符重载函数, 将本类数据转换成将本类数据转换成其他类型的数据。其他类型的数据。构造函数:构造函数:Complex:Complex(double r) real = r ; image = 0; 第29页/共57页第三十页,共57页。定义定义(dngy)类型转换函数类型转换函数: 功能:将功能:将 类对象自动类对象自动(zdng)转换成转换成 类型对象类型对象类型转换函数类型转换函数(hnsh)只能用成员函数只能用成员函数(hnsh)实现实现, 不能用友元函
36、数不能用友元函数(hnsh)实现。实现。在类内定义类型转换函数的一般格式为:在类内定义类型转换函数的一般格式为:operator ( ) . 在类外定义类型转换函数的一般格式为:在类外定义类型转换函数的一般格式为: : operator ( ) . 该函数不能有参数,该函数不能有参数,不能写返回值类型,不能写返回值类型, 因返回值类型已确定。因返回值类型已确定。第30页/共57页第三十一页,共57页。例例13.10 类型转换函数类型转换函数(hnsh)的定义和使用的定义和使用 #include class Complexdouble Real, Image;public:Complex(dou
37、ble r=0, double i=0) Real=r; Image=i; operator double ( ) / A 类型转换函数类型转换函数(hnsh), / 将将 Complex 类转换成类转换成 double 类类 return Real; ;void main( ) Complex c(3,2);double x;x = c; / B cout x= x endl;/ 即即 x = double (c) ;系统自动处理为系统自动处理为 x = c.operator double( );第31页/共57页第三十二页,共57页。例例13.11 成员函数成员函数(hnsh)和类型转换函
38、数和类型转换函数(hnsh)的比较的比较见见 “第第13章章 多态性多态性(例子例子).doc”其中其中(qzhng)主函数为:主函数为:void main(void)RMB r(23, 8, 6);int r1, r2, r3;r1= r ; /处理成处理成 r1 = r.operator int( );r2= int(r); /处理成处理成 r2 = r.operator int( ) ;r3= r.GetFen( ); coutr1=r1endl;coutr2=r2endl;coutr3=r3endl; 使用使用类型自动转换类型自动转换 较方便、自然。较方便、自然。第32页/共57页第三
39、十三页,共57页。13.2.4 其他其他(qt)运算符的重载运算符的重载1重载重载+、-运算符运算符 重载重载(zhn zi)前置前置 + 运算符的成员函数的一般格式为:运算符的成员函数的一般格式为: :operator+ ( ) . 重载重载后置后置 + 运算符的运算符的成员成员函数的一般格式为:函数的一般格式为: :operator+ (int) . int 用于区分,没有实际意义,用于区分,没有实际意义,可给出实参,也可以不给出实参。可给出实参,也可以不给出实参。第33页/共57页第三十四页,共57页。重载前置重载前置(qin zh) + 运算符的友元函数的一般格式为:运算符的友元函数的
40、一般格式为:friend operator+ ( &obj ) . 重载后置重载后置+运算符的友元函数运算符的友元函数(hnsh)的一般格式为:的一般格式为:friend operator+ ( &obj, int) . int 用于区分,没有实际意义,用于区分,没有实际意义,可给出实参,也可以不给出实参。可给出实参,也可以不给出实参。例例13.12 实现实现+和和 - 的前置和后置运算符重载,的前置和后置运算符重载, 程序见程序见 “第第13章章 多态性多态性(例子例子).doc”第34页/共57页第三十五页,共57页。13.2.5 字符串类字符串类C+ 提供的字符串处理能力
41、提供的字符串处理能力(nngl)较弱,如不能用运较弱,如不能用运算符直接对字符串对象进行加、减等操作,算符直接对字符串对象进行加、减等操作,而必须通过字符串处理函数来实现拷贝、连接等操作。而必须通过字符串处理函数来实现拷贝、连接等操作。如:如:char s110=abc, s210=123; strcpy(s1, s2); /不能写成不能写成 s1= s2; strcat(s1, s2); /不能写成不能写成 s1= s1+s2;能否定义一个字符串类:能否定义一个字符串类:String 实现:实现: String s1(abc), s2(123), s3; s1 = s2; s3 = s1 +
42、 s2;能能! 可以利用可以利用C+提供的运算符重载实现。提供的运算符重载实现。第35页/共57页第三十六页,共57页。例例13.18 定义字符串类定义字符串类String,并测试重载的运算,并测试重载的运算符以及成员符以及成员(chngyun)函数函数 程序见程序见 “第第13章章 多态性多态性(例子例子).doc”,或阅读教材,或阅读教材上的程序。上的程序。重点讲解重点讲解(jingji):(1) 说明:函数名后的说明:函数名后的 const(2) (拷贝拷贝)构造函数,在主函数中如何使用?构造函数,在主函数中如何使用?(3) 重载赋值重载赋值 = 运算符运算符(4) 重载重载 + 运算符
43、运算符(5) 类型转换函数类型转换函数 operator const char *(6) 删除子串图示见下页删除子串图示见下页第36页/共57页第三十七页,共57页。删除删除(shnch)子串:子串:String operator - (const String &s1, const char *s2 ) lenp1p2s1.Strps2t.Strp第37页/共57页第三十八页,共57页。13.3 静态静态(jngti)联编联编联编是指一个计算机程序彼此关联联编是指一个计算机程序彼此关联(gunlin)的过程。的过程。 在本章在本章(bn zhn)中指函数间调用关系的确定。中指函数间调
44、用关系的确定。按照联编所确定的时刻不同,可分为两种:按照联编所确定的时刻不同,可分为两种: 静态联编静态联编和和动态联编动态联编。 静态联编是指联编出现在编译连接阶段,静态联编是指联编出现在编译连接阶段, 即函数调用关系的确定是在程序执行之前。即函数调用关系的确定是在程序执行之前。这种联编又称早期联编,这种联编又称早期联编, 通过这种联编可实现静态多态。通过这种联编可实现静态多态。 第38页/共57页第三十九页,共57页。例例13.20 普通函数的静态联编普通函数的静态联编#include int add(int a, int b) /重载函数重载函数1 return(a+b); double
45、 add(double a, double b) /重载函数重载函数2 return(a+b); void main( ) coutadd(1, 2)t; /编译时确定调用重载函数编译时确定调用重载函数1 coutadd(1.1, 2.2)n; /编译时确定调用重载函数编译时确定调用重载函数2在编译连接阶段,就能根据在编译连接阶段,就能根据(gnj)参数的个数和类型确定参数的个数和类型确定调用的是哪一个函数。调用的是哪一个函数。 第39页/共57页第四十页,共57页。例例13.21 读书读书(d sh)上程序上程序 重点讲解重点讲解(jingji):double CalcArea( Point
46、 &p ) return(p.Area( ); /A 编译连接时确定调用函数编译连接时确定调用函数 1void main( ) Rectangle r(0, 0, 1, 1); Circle c(0, 0, 1); coutCalcArea( r )t; coutCalcArea( c )n;Point Rectangle Circle能否找到一种机制,能否找到一种机制,让让CalcArea( )函数变成一个函数变成一个通用的求面积通用的求面积(min j)的函数。的函数。这就是这就是C+提供的动态联编和提供的动态联编和虚函数应完成的工作。虚函数应完成的工作。 用派生类实参初始化基类型
47、参,用派生类实参初始化基类型参,p只能引用基类的成员。只能引用基类的成员。第40页/共57页第四十一页,共57页。13.4 动态动态(dngti)联编和虚函数联编和虚函数运行阶段才能运行阶段才能(cinng)确定函数的调用关系,这就是动态联编确定函数的调用关系,这就是动态联编 动态联编又称滞后动态联编又称滞后(zh hu)联编、晚期联编,联编、晚期联编, 动态联编技术能实现动态多态。动态联编技术能实现动态多态。 必须将类的成员函数定义成虚函数,必须将类的成员函数定义成虚函数, 才可以实现动态联编。才可以实现动态联编。 将成员函数定义成虚函数的格式为:将成员函数定义成虚函数的格式为:virtua
48、l ( ) 13.4.1 虚函数虚函数第41页/共57页第四十二页,共57页。重点重点(zhngdin)讲解:讲解:double CalcArea(Point &p) return( p.Area( ) ); /A Area( )是虚函数是虚函数void main( ) Point p(1, 2); Rectangle r(0, 0, 1, 1); Circle c(0, 0, 1); coutCalcArea( p )t CalcArea( r )t CalcArea( c )n;例例13.22 阅读阅读(yud)书上程序书上程序Area( )是虚函数是虚函数 ,C+ 规定规定(gu
49、dng),在在 A 行保留相关的行保留相关的三个虚函数入口地址三个虚函数入口地址 。在程序的运行阶段,在程序的运行阶段,根据实参的类型来确定根据实参的类型来确定调用哪一个虚函数。调用哪一个虚函数。通用的通用的求求面积函数面积函数第42页/共57页第四十三页,共57页。(1)派生类的虚函数必须)派生类的虚函数必须(bx)与基类虚函数同名,与基类虚函数同名, 且参数的类型、个数、顺序必须且参数的类型、个数、顺序必须(bx)一致,一致, 否则,属于函数重载,而不是虚函数。否则,属于函数重载,而不是虚函数。有关有关(yugun)虚函数的说虚函数的说明:明: (2)基类中虚函数)基类中虚函数(hnsh)
50、前的关键字前的关键字virtual不能缺省。不能缺省。 (3)必须通过基类对象的)必须通过基类对象的指针或引用指针或引用调用虚函数,调用虚函数, 才能实现动态多态。才能实现动态多态。 (4)虚函数必须是类的成员函数,不能是友元函数,)虚函数必须是类的成员函数,不能是友元函数, 也不能是静态成员函数。也不能是静态成员函数。 (5)不能将构造函数定义为虚函数,)不能将构造函数定义为虚函数, 但可将析构函数定义为虚函数。但可将析构函数定义为虚函数。 (6)调用虚函数速度较慢。因为,要实现动态多态,)调用虚函数速度较慢。因为,要实现动态多态, 在函数调用处必须保留多个虚函数的入口地址。在函数调用处必须
51、保留多个虚函数的入口地址。第43页/共57页第四十四页,共57页。例例13.23 在成员函数中调用虚函数在成员函数中调用虚函数程序见程序见 “第第13章章 多态性多态性(例子例子).doc”,或阅读或阅读(yud)教材上的程序。教材上的程序。我们注意,我们注意,在成员函数中调用成员函数时,在成员函数中调用成员函数时,系统都是通过对象自身的指针系统都是通过对象自身的指针this调用的,调用的,A类中的类中的fun2( )的实际被处理成如下形式:的实际被处理成如下形式:void fun2( ) cout A:fun2 fun3( ); /EB b;b.fun1( ); / 调用调用A类的类的fun
52、1( )和和fun2( ),在,在A类的类的fun2( )函数中,函数中, / 在在E行行, this 是指向是指向(zh xin)b的指针的指针, 所以调用所以调用B的的fun3( )函数函数第44页/共57页第四十五页,共57页。class Apublic: A( ) fun( ); virtual void fun( ) cout A:fun t; ;class B: public A public: B( ) fun( ); void fun( ) cout B:fun t; void g( ) fun( ); / 在成员在成员(chngyun)函数中调用虚函数函数中调用虚函数; A
53、B C 例例13.24 在构造函数中调用在构造函数中调用(dioyng)虚函数虚函数第45页/共57页第四十六页,共57页。class C: public B public:C( ) fun( ); void fun( ) cout C:fun n; ;void main( ) C c; /依次依次(yc)调用调用A、B、C三类的缺省构造函数三类的缺省构造函数 c.g( );运行运行(ynxng)结果:结果:A:fun B:fun C:funC:fun构造函数调用虚函数,调用的是类本身的虚函数。构造函数调用虚函数,调用的是类本身的虚函数。成员函数调用虚函数,遵循成员函数调用虚函数,遵循(zn
54、xn)动态多态性原则。动态多态性原则。ABC第46页/共57页第四十七页,共57页。13.4.2 虚析构函数虚析构函数(hnsh)如果类的构造函数中有动态申请如果类的构造函数中有动态申请(shnqng)的存储空间,的存储空间,在析构函数中应释放该空间。在析构函数中应释放该空间。此时,建议将析构函数定义为虚函数,此时,建议将析构函数定义为虚函数,以便实现通过基类的指针或引用以便实现通过基类的指针或引用撤消派生类对象时的多态性。撤消派生类对象时的多态性。 第47页/共57页第四十八页,共57页。#include class Achar *Aptr;public:A( ) Aptr = new ch
55、ar100; A( ) /析构函数析构函数(hnsh)不是虚函数不是虚函数(hnsh) delete Aptr; coutDelete Aptrendl; ;例例: 析构函数析构函数(hnsh)不是虚函数不是虚函数(hnsh)的情况的情况第48页/共57页第四十九页,共57页。class B : public A char *Bptr; public: B( ) Bptr=new char100; B( ) delete Bptr; coutDelete Bptrendl; ;void main(void)B b; 输出输出(shch)结果:结果:Delete BptrDelete Aptr系统自动撤销系统自动撤销(chxio)派生类对象派生类对象,不需要将析构函数定义为虚函数。不需要将析构函数定义为虚函数。第49页/共57页第五十页,共57页。void main(void)A *p=new B; delete p;A &p1=*(new B); delete &p1;输出输出(shch)结果:结果:Delete AptrDelete Aptr如果将析构函数定义成虚析构函
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年安徽新华图书音像连锁有限公司外包服务人员(第二批)补充招聘备考题库及完整答案详解一套
- 2026年中电(江门)综合能源有限公司招聘备考题库及答案详解一套
- 2026年国投湄洲湾港口有限公司招聘备考题库参考答案详解
- 2026年中国雄安集团有限公司校园招聘备考题库及1套参考答案详解
- 2026年中国食品安全报河南记者站招聘备考题库参考答案详解
- 2026年学年第一学期厦门市翔安区舫山第二小学公开招聘顶岗非在编合同教师备考题库及1套完整答案详解
- 2026年常州西电变压器有限责任公司招聘备考题库及1套完整答案详解
- 2026年广安市中医医院公开招聘6名劳务派遣工作人员的备考题库及答案详解参考
- 海南省海口市湖南师大附中海口中学2026届高一上数学期末学业水平测试模拟试题含解析
- 2026届山东省临沂市十九中高三英语第一学期期末监测模拟试题含解析
- 2024年居间服务合同:律师事务所合作与业务推广
- 全球变暖课件高级
- 农贸市场保洁服务 投标方案(技术标 )
- 合作的合同书模板
- 高压气瓶固定支耳加工工艺设计
- (正式版)FZ∕T 13061-2024 灯芯绒棉本色布
- 0.4kV配网不停电作业用工器具技术条件V11
- 满腹经纶相声台词完整篇
- 2023年10月自考05678金融法试题及答案含评分标准
- 新苏教版六年级科学上册第一单元《物质的变化》全部教案
- 城镇道路工程施工与质量验收规范CJJ解析及质量控制点
评论
0/150
提交评论