《第5章 多态性与虚函数.ppt》由会员分享,可在线阅读,更多相关《第5章 多态性与虚函数.ppt(70页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第5章章 多态性多态性5.1 多态性概述多态性概述u所谓所谓多态性多态性就是不同对象收到就是不同对象收到相同的请求相同的请求消息消息时,产生时,产生不同的动作不同的动作。l直观地说,多态性是指用直观地说,多态性是指用一个名字定义不同的函数一个名字定义不同的函数,这些函数执行不同但又类似的操作,从而可以使用这些函数执行不同但又类似的操作,从而可以使用相同的调用方式来调用这些具有不同功能的同名函相同的调用方式来调用这些具有不同功能的同名函数。即数。即“一个接口,多种方法一个接口,多种方法”。u5.1.1 多态的分类多态的分类lC+中的多态性可以分为四类中的多态性可以分为四类:参数多态参数多态:函
2、数模板、类模板实例化产生的多态行为函数模板、类模板实例化产生的多态行为包含多态包含多态:通过虚函数实现的、定义于不同类中的同名成:通过虚函数实现的、定义于不同类中的同名成员函数的多态行为员函数的多态行为重载多态重载多态:通过函数重载和运算符重载实现通过函数重载和运算符重载实现的多态行为的多态行为强制多态强制多态:通过通过强制类型转化强制类型转化实现实现的多态行为。的多态行为。前面两种统称为前面两种统称为通用多态通用多态,而后面两种统称为,而后面两种统称为专用多态专用多态。5.1 多态性概述多态性概述u 5.1.2多态的实现多态的实现 l多多态态从从实实现现的的角角度度来来讲讲可可以以划划分分为
3、为两两类类:编编译译时的多态时的多态和和运行时的多态运行时的多态。编编译译时时的的多多态态是是通通过过静静态态联联编编来来实实现现的的。静静态态联联编编就就是是在在编编译译阶阶段段完完成成的的联联编编。编编译译时时多多态态性性主主要是要是通过函数重载和运算符重载实现通过函数重载和运算符重载实现的。的。运行时的多态运行时的多态是用是用动态联编动态联编实现的。动态联编是实现的。动态联编是运行阶段完成的联编。运行时多态性主要是运行阶段完成的联编。运行时多态性主要是通过通过虚函数来实现虚函数来实现的。的。5.2运算符重载运算符重载问题举例问题举例问题举例问题举例复数的运算复数的运算复数的运算复数的运算
4、l定义一个简化的复数类定义一个简化的复数类complex:class complex public:double real,imag;complex(double r=0,double i=0)real=r;imag=i;l若要把类若要把类complex的两个对象的两个对象com1和和com2加在一起加在一起,下面的语句是不能实下面的语句是不能实现的现的:main()complex com1(1.1,2.2),com2(3.3,4.4),total;total=com1+com2;/错误错误 /return 0;l即用即用“+”、“-”能够实现复数的加减运算,如果想实现,能够实现复数的加减运算
5、,如果想实现,必须对运算符进行重载。必须对运算符进行重载。5.2.1运算符重载概述运算符重载概述u运算符重载是对已有的运算符赋予多重含运算符重载是对已有的运算符赋予多重含义义u必要性必要性lC+中预定义的运算符其运算对象只能是基中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如本数据类型,而不适用于用户自定义类型(如类)类)u实现机制实现机制l将指定的运算表达式转化为对运算符函数的将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。调用,运算对象转化为运算符函数的实参。l编译系统对重载运算符的选择,遵循函数重编译系统对重载运算符的选择,遵循函数重
6、载的选择原则。载的选择原则。5.2.1运算符重载概述运算符重载概述规则和限制规则和限制规则和限制规则和限制u可以重载可以重载可以重载可以重载C+C+中除下列运算符外的所有运算符:中除下列运算符外的所有运算符:中除下列运算符外的所有运算符:中除下列运算符外的所有运算符:.*:?:.*:?:u只能重载只能重载只能重载只能重载C+C+语言中已有的运算符,不可臆造新的。语言中已有的运算符,不可臆造新的。语言中已有的运算符,不可臆造新的。语言中已有的运算符,不可臆造新的。u不改变原运算符的优先级和结合性。也不改变运算符不改变原运算符的优先级和结合性。也不改变运算符不改变原运算符的优先级和结合性。也不改变
7、运算符不改变原运算符的优先级和结合性。也不改变运算符的语法结构,即单目运算符只能重载为单目运算符,的语法结构,即单目运算符只能重载为单目运算符,的语法结构,即单目运算符只能重载为单目运算符,的语法结构,即单目运算符只能重载为单目运算符,双目运算符只能重载为双目运算符双目运算符只能重载为双目运算符双目运算符只能重载为双目运算符双目运算符只能重载为双目运算符u不能改变操作数个数。不能改变操作数个数。不能改变操作数个数。不能改变操作数个数。u经重载的运算符,其操作数中至少应该有一个是自定经重载的运算符,其操作数中至少应该有一个是自定经重载的运算符,其操作数中至少应该有一个是自定经重载的运算符,其操作
8、数中至少应该有一个是自定义类型。义类型。义类型。义类型。u编译程序对运算符重载的选择遵循函数重载的选择规编译程序对运算符重载的选择遵循函数重载的选择规编译程序对运算符重载的选择遵循函数重载的选择规编译程序对运算符重载的选择遵循函数重载的选择规则则则则三种形式:三种形式:u在类外定义的普通函数在类外定义的普通函数u重载为类成员函数。重载为类成员函数。u重载为友元函数。重载为友元函数。5.2.1运算符重载概述运算符重载概述5.2.2 在类外定义的运算符重载函数在类外定义的运算符重载函数u声明形式声明形式函数类型函数类型 operator 运算符(形参)运算符(形参).例:例:例:例:5.15.1#
9、includeclass complex public:double real,imag;complex(double r=0,double i=0)real=r;imag=i;/复数类定义复数类定义5.2.2 在类外定义的运算符重载函数在类外定义的运算符重载函数complex operator+(complex,co1,complex co2)complex temp(co1.real+co2.real,co1.imag+co2.imag);return temp;/运算符重载运算符重载main()complex com1(1.1,2.2),com2(3.3,4.4),total1,tota
10、l2;total2=com1+com2;total1=operator+(com1,com2);cout“real1=”total1.real“imag1=”total1.imag1endl;cout“real2=”total2.real“imag2=”total2.imag1endl return 0;/两种方法调用两种方法调用在在C+中中,可可以以把把运运算算符符重重载载函函数数定定义义成成某某个个类类的的友友元元函数函数,称为友元运算符函数。称为友元运算符函数。l1.友元运算符函数定义的语法形式友元运算符函数定义的语法形式友元运算符函数的原型在类的内部声明格式如下友元运算符函数的原型在类
11、的内部声明格式如下:class X /friend 返回类型返回类型 operator运算符运算符(形参表形参表);/在类外定义友元运算符函数的格式如下在类外定义友元运算符函数的格式如下:返回类型返回类型 operator运算符运算符(形参表形参表)函数体函数体 5.2.3友元运算符函数友元运算符函数5.2.3友元运算符函数友元运算符函数u例例用友员函数重载算术运算符用友员函数重载算术运算符#include#include iostream.hiostream.h class point class point intint x,yx,y;public:public:point(intpoin
12、t(int x1=0,int y1=0)x=x1;y=y1;x1=0,int y1=0)x=x1;y=y1;friendfriend point point operatoroperator +(const point&p1,const point&p2););friendfriend point point operatoroperator +(point&point&p)p)p.xp.x+;+;p.yp.y+;return p;+;return p;void print()void print()coutcout x y x y=()-l2.双目运算符重载双目运算符重载友元函数不是类的成员
13、函数,没有友元函数不是类的成员函数,没有友元函数不是类的成员函数,没有友元函数不是类的成员函数,没有thisthis指针。这样,用指针。这样,用指针。这样,用指针。这样,用友元函数友元函数友元函数友元函数重载双目运算符重载双目运算符重载双目运算符重载双目运算符时,时,时,时,友元函数有友元函数有友元函数有友元函数有2 2个参数个参数个参数个参数,重重重重载单目运算符载单目运算符载单目运算符载单目运算符时,要时,要时,要时,要有有有有1 1个参数个参数个参数个参数。当用友元函数重载双目运算符时当用友元函数重载双目运算符时当用友元函数重载双目运算符时当用友元函数重载双目运算符时,2,2个操作数都要
14、传递给个操作数都要传递给个操作数都要传递给个操作数都要传递给运算符函数。运算符函数。运算符函数。运算符函数。例例例例5.2.2 5.2.2 用友元运算符函数进行复数运算。用友元运算符函数进行复数运算。用友元运算符函数进行复数运算。用友元运算符函数进行复数运算。#include#include class class complexcomplex publicpublic:complex(doublecomplex(double r=0.0 r=0.0,double i=0.0);double i=0.0);5.2.3友元运算符函数友元运算符函数5.2.3友元运算符函数友元运算符函数 void
15、print();void print();/用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符“+”+”friendfriend complexcomplex operatoroperator +(complex a(complex a,complex b);complex b);/用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符“-”-”friendfriend complexcomplex operatoroperator -(complex a(complex a,complex
16、 b);complex b);/用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符“*”“*”friendfriend complexcomplex operatoroperator *(complex a(complex a,complex b);complex b);/用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符用友元运算符函数重载运算符“/”/”friendfriend complexcomplex operatoroperator /(complex a(complex a,complex b);c
17、omplex b);privateprivate:double real;/double real;/复数实部复数实部复数实部复数实部 double double imagimag;/;/复数虚部复数虚部复数虚部复数虚部;5.2.3友元运算符函数友元运算符函数 complex:complex(double r,double i)/构造函数构造函数 real=r;imag=i;complex operator+(complex a,complex b)/重载运算符重载运算符“+”的实现的实现 complex temp;temp.real=a.real+b.real;temp.imag=a.ima
18、g+b.imag;return temp;complex operator-(complex a,complex b)/重载运算符重载运算符“-”的实现的实现 complex temp;temp.real=a.real-b.real;temp.imag=a.imag-b.imag;return temp;5.2.3友元运算符函数友元运算符函数complex operator*(complex a,complex b)/重载运算符重载运算符“*”的实的实现现 complex temp;temp.real=a.real*b.real-a.imag*b.imag;temp.imag=a.real*b
19、.imag+a.imag*b.real;return temp;complex operator/(complex a,complex b)/重载运算符重载运算符“/”的实的实现现 complex temp;double t;t=1/(b.real*b.real+b.imag*b.imag);temp.real=(a.real*b.real+a.imag*b.imag)*t;temp.imag=(b.real*a.imag-a.real*b.imag)*t;return temp;void complex:print()/显示输出复数显示输出复数 cout0)cout+;if(imag!=0)
20、coutimagin;5.2.3友元运算符函数友元运算符函数int main()complex A1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6;/定义六个复数类对象定义六个复数类对象 A3=A1+A2;/复数相加复数相加 A4=A1-A2;/复数相减复数相减 A5=A1*A2;/复数相乘复数相乘 A6=A1/A2;/复数相除复数相除 A1.print();/输出复数输出复数A1 A2.print();/输出复数输出复数A2 A3.print();/输出复数相加结果输出复数相加结果A3 A4.print();/输出复数相减结果输出复数相减结果A4 A5.print();/
21、输出复数相乘结果输出复数相乘结果A5 A6.print();/输出复数相除结果输出复数相除结果A6 return 0;程序运行结果为:程序运行结果为:2.3+4.6i3.6+2.8i5.9+5.2.4i-1.3+1.8i-4.6+23i1.01731+0.486538i A3=operator+(A1,A2);A4=operator-(A1,A2);A5=operator*(A1,A2);A6=operator/(A1,A2);相相相相当当当当于于于于一般而言一般而言,如果在类如果在类X中采用中采用友元函数重友元函数重载双目运算符载双目运算符,而而aa和和bb是类是类X的两个对的两个对象象,则
22、以下两种函数调用方法是等价的则以下两种函数调用方法是等价的:aa bb;/隐式调用 operator(aa,bb);/显式调用5.2.3友元运算符函数友元运算符函数l3.单目运算符重载单目运算符重载用友元函数重载单目运算符时,需要一个显式的操作数。用友元函数重载单目运算符时,需要一个显式的操作数。例例5.2.3 用友元函数重载单目运算符用友元函数重载单目运算符“-”。#includeclass AB public:AB(int x=0,int y=0)a=x;b=y;friend AB operator-(AB obj);/声明重载单目运算符声明重载单目运算符“-”void print();p
23、rivate:int a,b;5.2.3友元运算符函数友元运算符函数5.2.3友元运算符函数友元运算符函数AB operator-(AB obj)/定义重载单目运算符定义重载单目运算符“-”obj.a=-obj.a;obj.b=-obj.b;return obj;void AB:print()couta=a b=bendl;main()AB ob1(50,60),ob2;ob1.print();ob2=-ob1;ob2.print();return 0;与与obj对象对对象对应的实参数对应的实参数对象会变吗象会变吗?程序运行的输出结果程序运行的输出结果:a=50 b=60a=-50 b=-60
24、5.2.3友元运算符函数友元运算符函数l【例例5.2.4】使用友元函数重载使用友元函数重载“+”、“-”运算符,可能运算符,可能会出现一些问题会出现一些问题#include class coord public:coord(int i=0,int j=0);void print();friend coord operator+(coord op);/声明友元运算符函数声明友元运算符函数operator+()private:/采用对象参数传递操作数采用对象参数传递操作数 int x,y;coord:coord(int i,int j)x=i;y=j;void coord:print()cout
25、x:x,y:yendl;coordcoord operator+(operator+(coordcoord op)op)对象参数对象参数的引用的引用5.2.3友元运算符函数友元运算符函数coord operator+(coord op)/友元运算符函数友元运算符函数operator+()的实现的实现 +op.x;+op.y;return op;main()coord ob(10,20);ob.print();operator+(ob);/显式调用友元运算符函数显式调用友元运算符函数 operator+()ob.print();+ob;/隐式调用友元运算符函数隐式调用友元运算符函数 operat
26、or+()ob.print();return 0;程序运行的输出结果:程序运行的输出结果:x:10,y:20 x:10,y:20 x:10,y:20程序运行的输出结果:程序运行的输出结果:程序运行的输出结果:程序运行的输出结果:x:10,y:20 x:11,y:21x:12,y:22coordcoord operator+(operator+(coordcoord op)op)一般而言,如果在类X中采用友元函数重载单目运算符,而aa是类X的对象,则以下两种函数调用方法是等价的:aa;/隐式调用 operator(aa);/显式调用 关于友元函数重载单目运算符后缀方式的表示方法在后面将介绍。5.
27、2.3友元运算符函数友元运算符函数l在C+中,可以把运算符函数定义成某个类的成员函数,称为成员运算符函数。l1.成员运算符函数定义的语法形式成员运算符函数定义的语法形式成员运算符函数的原型在类的内部声明格式如下:class X /返回类型返回类型 operator运算符运算符(形参表形参表);/;在类外定义成员运算符函数的格式如下:返回类型返回类型 X:operator 运算符运算符(形参表形参表)函数体函数体 5.2.4成员运算符函数成员运算符函数5.2.4成员运算符函数成员运算符函数 例例例例 用成员函数重载算术运算符用成员函数重载算术运算符用成员函数重载算术运算符用成员函数重载算术运算符
28、#include iostream.h class point int x,y;public:point(int x1=0,int y1=0)x=x1;y=y1;point operator+(point p1);point operator+()x+;y+;return*this;void print()cout x y endl;point point:operator+(point p1)point p;p.x=x+p1.x;p.y=y+p1.y;return p;void main()point p1(10,10),p2(20,20);p1=p1+p2;p1.print();+p1;p
29、1.print();编译程序解释为编译程序解释为:p1.operator+(p2);编译程序解释为编译程序解释为:p1.operator+()this.x this.y与一般成员函数一样,与一般成员函数一样,运算符函数中隐含有运算符函数中隐含有this指针,用于指向调指针,用于指向调用该成员函数的对象。用该成员函数的对象。使用成员函数重载运算符时,双目使用成员函数重载运算符时,双目运算符仅有一个参数,单目运算符运算符仅有一个参数,单目运算符不要参数。不要参数。this.x this.yl2.双目运算符重载双目运算符重载对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作
30、数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。例例 下标运算符下标运算符 的重载。的重载。在C+中对数组不进行下标越界检查,利用C+类,通过重载,可定义一种更安全、功能更强的数组类型。#include iostream.h class carray char*buff;int length;public:carray(int i)length=i;buff=new charlength;carray()delete buff;int getlength()return length;char&operator(int i);5.2.4成员运算符函数成员运算符函数
31、使用成员函数重使用成员函数重载,仅有一个载,仅有一个int参数,返回引用参数,返回引用(以便实现数组元以便实现数组元素作赋值的左操素作赋值的左操作数作数)。5.2.4成员运算符函数成员运算符函数char&carray:operator(int i)static char ch=0;if(i=0)return buffi;else cout Subscript out of range!n;return ch;void main()int i;char c;carray string1(16);for(i=0;i c;string1i=c;/cin string1i;/string1.opera
32、tor(i)=c;for(i=0;i 9;i+)cout string1i;重载下标运算符时,重载下标运算符时,运算符函数只能有一个参数,不可运算符函数只能有一个参数,不可带多个参数;带多个参数;不能用友元函数进行重载不能用友元函数进行重载,且运算符函数必须,且运算符函数必须是非静态成员函数是非静态成员函数5.2.45.2.4成员运算符函数成员运算符函数成员运算符函数成员运算符函数 例例 重载函数运算符重载函数运算符()()#include iostream.h class array int rows,cols;double*element;public:array(int r,int c)
33、rows=r;cols=c;element=new doubler*c;array()delete element;double&operator()(int r,int c)return*(element+r*cols+c);void main()array a(2,3);int i,j;for(i=0;i2;i+)for(j=0;j 3;j+)a(i,j)=j;for(i=0;i2;i+)for(j=0;j 3;j+)cout a(i,j);使用成员函数重使用成员函数重载,仅有两个载,仅有两个int参数,返回引用参数,返回引用(以便实现数组元以便实现数组元素作赋值的左操素作赋值的左操作数作
34、数)。l一般而言,如果在类X中采用成员函数重载双目运算符,成员运算符函数operator 所需的一个操作数由对象aa通过this指针隐含地传递,它的另一个操作数bb在参数表中显示,aa和bb是类X的两个对象,则以下两种函数调用方法是等价的:aa bb;/隐式调用 aa.operator(bb);/显式调用 5.2.4成员运算符函数成员运算符函数l3.单目运算符重载单目运算符重载对对单单目目运运算算符符而而言言,成成员员运运算算符符函函数数的的参参数数表表中中没没有有参参数数,此此时时当当前前对对象象作作为为运运算算符符的的一一个个操操作作数。数。一一般般而而言言,采采用用成成员员函函数数重重载
35、载单单目目运运算算符符时时,以以下两种方法是等价的下两种方法是等价的:aa;/隐式调用 aa.operator();/显式调用成成员员运运算算符符函函数数operator 所所需需的的一一个个操操作作数数由由对对象象aa通通过过this指指针针隐隐含含地地传传递递。因因此此,在在它它的参数表中没有参数。的参数表中没有参数。5.2.4成员运算符函数成员运算符函数u4 成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较l(1)对对双目运算符双目运算符而言而言,成员运算符函数成员运算符函数带有一个参带有一个参数数,而而友元运算符函数友元运算符函数带有两个参数带有两个参数;对对单
36、目运算符单目运算符而言而言,成员运算符函数成员运算符函数不带参数不带参数,而而友元运算符函数友元运算符函数带一个参数带一个参数。l(2)双目运算符双目运算符一般一般可可以被重载以被重载为友元运算符函数为友元运算符函数或或成员运算符函数成员运算符函数,但有一种情况但有一种情况,必须使用友元函必须使用友元函数。数。运算符的左操作数不是类对象,如:运算符的左操作数不是类对象,如:obj=200+obj1;则在右操作数对象的类中只能使用则在右操作数对象的类中只能使用友元函数重载该运算符友元函数重载该运算符l(3)成员运算符函数和友元运算符函数可以用成员运算符函数和友元运算符函数可以用习惯方习惯方式调用
37、式调用,也可以用它们也可以用它们专用的方式调用专用的方式调用。l(4)C+的大部分运算符的大部分运算符既可说明为成员运算符函数既可说明为成员运算符函数,又可说明为友元运算符函数。究竟选择哪一种运算又可说明为友元运算符函数。究竟选择哪一种运算符好一些符好一些,没有定论没有定论,这主要取决于实际情况和程序这主要取决于实际情况和程序员的习惯。员的习惯。5.2.4成员运算符函数成员运算符函数uu1 1 单目运算符单目运算符单目运算符单目运算符“+”+”和和和和“-”-”的重载的重载的重载的重载 l在在C+中中,可可以以通通过过在在运运算算符符函函数数参参数数表表中中是是否否插插入入关关键键字字int来
38、区分前缀和后缀这两种方式。来区分前缀和后缀这两种方式。对于前缀方式对于前缀方式+ob,可以用运算符函数重载为可以用运算符函数重载为 ob.operator+();/成员函数重载成员函数重载 或或 operator+(X&ob);/友元函数重载友元函数重载,其中其中ob为类为类X对象的引用对象的引用对于后缀方式对于后缀方式ob+,可以用运算符函数重载为可以用运算符函数重载为 ob.ooperator+(int);/成员函数重载成员函数重载 或或 operator+(X&ob,int);/友元函数重载友元函数重载在调用后缀方式的函数时在调用后缀方式的函数时,参数参数int一般被传递给值一般被传递给
39、值0。5.2.5 几个常用运算符的重载几个常用运算符的重载u2 2 赋值运算符赋值运算符赋值运算符赋值运算符“=”=”的重载的重载的重载的重载 对任一类X,如果没有用户自定义的赋值运算符函数,那么系统自动地为其生成一个缺省的赋值运算符函数,定义为类X中的成员到成员的赋值,例如:X&X:operator=(const X&source)/成员间赋值成员间赋值 若obj1和obj2是类X的两个对象,obj2已被创建,则编译程序遇到如下语句:obj1=obj2;就调用缺省的赋值运算符函数,将对象obj2的数据成员的值逐个赋给对象obj1的对应数据成员中。5.2.5 几个常用运算符的重载几个常用运算符
40、的重载l3.指针悬挂问题在某些特殊情况下,如类中有指针类型时,使用缺省的赋值运算符函数会产生错误。例例5.2.11 使用缺省的赋值运算符函数产生错误的例使用缺省的赋值运算符函数产生错误的例子。子。#include#include class string public:string(char*s)ptr=new charstrlen(s)+1;strcpy(ptr,s);5.2.5 几个常用运算符的重载几个常用运算符的重载string()delete ptr;void print()coutptrendl;private:char*ptr;void main()string p1(book);
41、string p2(pen);p1=p2;coutp2:;p2.print();coutp1:;p1.print();5.2.5 几个常用运算符的重载几个常用运算符的重载产生指针产生指针悬挂问题悬挂问题l l4.4.重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题为了解决上述使用缺省的赋值运算符所遇到的指针悬挂问题,必须重载赋值运算符,使得对目标对象数据成员指针的赋值,是把原对象指针ptr所指向的内容传递给它,而不是简单地传递指针值。例例5.2.12 重载赋值运算符解决指针悬挂问题。重载赋值运算符解决指针悬挂问题。#inc
42、lude#include class string public:string(char*s)ptr=new charstrlen(s)+1;strcpy(ptr,s);string()delete ptr;void print()coutptrendl;5.2.5 几个常用运算符的重载几个常用运算符的重载 string&operator=(const string&);/声明赋值运算符重载函数声明赋值运算符重载函数private:char*ptr;string&string:operator=(const string&s)/定义赋值运算符重载函数定义赋值运算符重载函数 if(this=&s
43、)return*this;/防止防止s=s的赋值的赋值 delete ptr;/释放掉原区域释放掉原区域 ptr=new charstrlen(s.ptr)+1;/分配新区域分配新区域 strcpy(ptr,s.ptr);/字符串拷贝字符串拷贝 return*this;void main()string p1(book);string p2(pen);p1=p2;coutp2:;p2.print();coutp1:;p1.print();5.2.5 几个常用运算符的重载几个常用运算符的重载解决指针解决指针悬挂问题悬挂问题5.3 类型转换类型转换uu5.3.15.3.1系统预定义类型间的转换系统
44、预定义类型间的转换系统预定义类型间的转换系统预定义类型间的转换l1.隐式类型转换隐式类型转换C语言规定的类型转换:赋值转换、整型统一转换语言规定的类型转换:赋值转换、整型统一转换int、低、低级别类型向高级别类型(如级别类型向高级别类型(如charint float double)转换转换l2.显式类型转换显式类型转换(类型名类型名)表达式表达式int i,j /cout(float)(i+j);类型名类型名(表达式表达式)int i,j;/coutfloat(i+j);5.3 类型转换类型转换uu5.3.2 5.3.2 类类型与系统预定义类型间的转换类类型与系统预定义类型间的转换类类型与系统
45、预定义类型间的转换类类型与系统预定义类型间的转换l1通过构造函数进行类型转换通过构造函数进行类型转换 必须有一个前提,那就是此类一定有一个必须有一个前提,那就是此类一定有一个只带一个参数的只带一个参数的构造函数构造函数。例例例例#include#include iostream.hiostream.h class class abab double m;double m;public:public:ab()mab()m=0;=0;ab(doubleab(double i)mi)m=i;/(1)=i;/(1)ab(charab(char*s,ints,int j=0)/(2)j=0)/(2)m=
46、m=strlen(sstrlen(s););5.3 类型转换类型转换void void print()coutprint()cout m m endlendl;void main()void main()class class abab a(5);a=10;a(5);a=10;a.printa.print();a=1234;();a=1234;a.printa.print();();上例中构造函数上例中构造函数上例中构造函数上例中构造函数(1)(1)完成从完成从完成从完成从 intint 型到型到型到型到class class abab类类类类类类类类型的转换;构造函数型的转换;构造函数型的转
47、换;构造函数型的转换;构造函数(2)(2)完成从完成从完成从完成从char*char*到到到到class class abab类类类类类类类类型的转换,虽然它有型的转换,虽然它有型的转换,虽然它有型的转换,虽然它有2 2个参数,但第个参数,但第个参数,但第个参数,但第2 2个参数是缺省。个参数是缺省。个参数是缺省。个参数是缺省。使用构造函数实现类型转换,只能从参数类型到向使用构造函数实现类型转换,只能从参数类型到向使用构造函数实现类型转换,只能从参数类型到向使用构造函数实现类型转换,只能从参数类型到向类类型转换,而不能从类类型向基本类型转换。类类型转换,而不能从类类型向基本类型转换。类类型转换
48、,而不能从类类型向基本类型转换。类类型转换,而不能从类类型向基本类型转换。5.3 类型转换类型转换l2通过类类型转换函数进行类型转换通过类类型转换函数进行类型转换 类类型转换函数专门用来类类型转换函数专门用来将类类型向基本类型转换将类类型向基本类型转换的。为类的。为类定义一个定义一个类类型转换函数的语法类类型转换函数的语法为:为:operator()return;类类型转换函数没有返回类型说明,但函数体必须有类类型转换函数没有返回类型说明,但函数体必须有类类型转换函数没有返回类型说明,但函数体必须有类类型转换函数没有返回类型说明,但函数体必须有returnreturn语句,用于返回语句,用于返
49、回语句,用于返回语句,用于返回 。基类型名基类型名基类型名基类型名即转换的即转换的即转换的即转换的目标类型目标类型目标类型目标类型名名名名。不进行返回值不进行返回值的类型说明的类型说明 例例例例#include#include iostream.hiostream.h class class abab intint x;x;public:public:ab(intab(int a=0)x=a;a=0)x=a;operator operator intint();();5.3 类型转换类型转换void print()void print()coutcout x x endlendl;abab:o
50、peratoroperator intint()()retuenretuen x;x;void main()void main()abab a1(123);a1(123);intint b1;b1=a1;b1;b1=a1;/b1=int(a1);/b1=int(a1);coutcout b1 b1 endlendl;定义类类型转换函数时,应注意下列几点:定义类类型转换函数时,应注意下列几点:定义类类型转换函数时,应注意下列几点:定义类类型转换函数时,应注意下列几点:n转换函数转换函数是类的是类的非静态成员函数非静态成员函数。n转换函数定义转换函数定义时,时,不进行返回值的类型说明不进行返回值的