第11章 友元与运算符重载
{ t.x++; t.y++;t.z++; return t; }
ThreeD operator ++ (ThreeD & t,int i) { ThreeD temp =t; t.x++; t.y++;t.z++; return temp; }
void main(void)
{ ThreeD m1(25,50,100),m2(1,2,3),m3; m1.Show(); ++m1;
m1.Show(); m2++;
m2.Show();
m3=++m1+m2++; m3.Show(); }
程序执行后输出:
x=25 y=50 z=100 x=26 y=51 z=101 x=2 y=3 z=4 x=29 y=55 z=106
·295·
程序中定义的类ThreeD描述一个空间点的三维坐标,对对象执行“++”运算,即对该点坐标的三个分量(x,y,z)分别完成加1运算。主函数中:
++m1 语句被解释为对前置++运算符重载函数的调用: opreator++(m1); 运算后m1=(26,51,101)。
m2++ 语句被解释为对后置++运算符重载函数的调用: opreator++(m2,1);运算后m2=(2,3,4)。 m3=++m1+m2++语句的执行将分为三步, 第一步执行对m1的前置++运算:++m1 运算结果是返回m1自加后的一个对象,若将此对象记作t1,则t1=++m1=(27,52,102)。 第二步执行对m2的后置++运算:m2++
运算结果将返回m2自加前的对象,若将此对象记作t2,则t2=m2++=(2,3,4)。 第三步执行将二个对象t1与t2的“和”赋给m3运算:m3=t1+t2 该运算被解释为对“+”运算符重载函数的调用:
m3=t1.preator+(t2); 运算的结果为m3=(27,52,102)+(2,3,4)=(29,55,106) 。
第11章 友元与运算符重载 ·296·
11.2.4 转换函数 有时需要将类类型数据转换成另一种数据类型,如将人民币类中的元、角、分转换成以分为单位的实数。为此,C++提供了相应的类型转换函数,这种类型转换函数必须由用户在类中定义为成员函数,其一般格式为:
<类名>::operator <转换后数据类型>( ) {函数体}
该转换函数的函数名为:operator <转换后数据类型>,且无参数,其返回类型为<转换后数据类型>,转换函数的作用是将对象内的数据成员转换成“转换后数据类型”。
【例11.11】定义一个时间计数器类TCount,类中数据成员为时、分、秒。编写类型转换函数,将时、分、秒变成一个以秒为单位的等价实数。
# include
int Hour,Minute,Second; public:
TCount (int h=0,int m=0,int s=0) { Hour=h;Minute=m;Second=s;}
operator float(); //A { float second;
second=Hour*3600+Minute*60+Second; return second; } };
void main(void)
{ TCount t(1,20,5); float s1,s2,s3;
s1=t; //B s2=float (t); //C s3=(float ) t; //D
cout<<\}
程序执行后输出:
s1=4805 s2=4805 s3=4805
说明: (1)A行定义的转换函数将对象中三个数据成员时、分、秒转换为以秒为单位的实数,并返回实数值。
(2)B行中表达式s1=t 由编译器将其转换为对转换函数的调用:
第11章 友元与运算符重载 ·297·
s1=t.operator float();
通过调用转换函数将对象t中的数据成员转换为实数后赋给s1。即进行如下运算: s1=Hour*3600+Minute*60+Second=1*3600+20*60+5=4805
(3)C行中表达式s2= float(t)由编译器将其变换为对转换函数的调用: s2=t.operator float ();
同理D行中表达式也调用了转换函数:
s3==t.operator float ();
在B、C、D行中虽然转换方式不同,但都调用转换函数operator float (),完成时间计数器类到实数的数据转换工作。
11.2.5 字符串类运算符重载
C++系统提供的字符串处理能力比较弱,字符串复制、连接、比较等操作不能直接通过“=”、“+”、“>”等运算操作符完成,而必须通过字符处理函数来完成的。例如,有字符串s1=”ABC”,s2=”DEF”,要完成s=s1+s2=“ABCDEF”的工作,则需要调用字符串处理函数:strcpy(s,s1)与strcat(s,s2)才能完成两个字符串的拼接工作。但通过C++提供的运算符重载机制,可以提供对字符串直接操作的能力,使得对字符串的操作与对一般数据的操作一样方便。如字符串s1与s2拼接成字符串s的工作,用“+”与“=”运算符组成的表达式:s=s1+s2即可完成。下面通过例题说明字符串运算符重载函数的编写方法,及重载后字符串运算符的使用方法。
【例11.12】编写字符串运算符“=”、“+”、“>”的重载Sp→ “A” 函数,使运算符“=”、“+”、“>”分别用于字符串的赋值、“B” Length 拼接、比较运算,实现字符串直接操作运算。 “C” 分析:字符串可用指向字符串的指针Sp及字符串长度? Length来描述,如图11.4所示。因此描述字符串类的数据成“\\0” 员为字符指针Sp及其长度Length。设计缺省构造函数、拷贝 图11.4 描述字符串类的数据成员 构造函数及初始化构造函数。再设计“=”、“+”、“>”运算
符重载函数,分别完成字符串赋值、拼接、比较运算。在主函数中先定义字符串对象,并调用构造函数完成初始化工作。然后使用“=”、“+”、“>”运算符,直接完成字符串的赋值、拼接、比较运算。程序设计如下:
# include
//定义字符串类
{ protected : int Length; char *Sp; public:
String() {Sp=0;Length=0;} String(const String &);
//定义缺省的构造函数 //定义拷贝构造函数
第11章 友元与运算符重载
String(const char *s)
//定义初始化构造函数
{ Length=strlen(s);
Sp=new char[Length +1]; strcpy(Sp,s); }
~String() { if (Sp) delete [] Sp;}
void Show()
·298·
//定义析构函数 //定义显示字符串函数
{ cout< void operator = (String &); //定义字符串赋值成员函数 friend String operator + ( const String &, const String &); //定义字符串拼接友元函数 int operator > (const String &) ; //定义字符串比较成员函数 }; String::String(const String &s) { Length=s.Length; if (s.Sp) { Sp=new char [Length+1]; strcpy(Sp,s.Sp); } else Sp=0; } void String::operator=(String &s) { if (Sp) delete []Sp; Length=s.Length; if (s.Sp) { Sp=new char [Length+1]; strcpy(Sp,s.Sp); } else Sp=0; } String operator + (const String &s1,const String &s2) { String t; t.Length=s1.Length+s2.Length; t.Sp=new char [t.Length+1]; strcpy(t.Sp,s1.Sp); strcat(t.Sp,s2.Sp); return t; } int String::operator >(const String &s) 第11章 友元与运算符重载 { if (strcmp(Sp,s.Sp)>0 ) return 1; else 0; } void main (void) { String s1(\ String s4(s1),s5,s6,s7; s5=s2; s6=s4+s3; s7=s5+s3; s6.Show(); s7.Show(); if (s4>s5) s4.Show(); else s5.Show(); } 程序执行后输出: software design hardware design software ·299· 关于上述程序有几点说明如下: (1)定义初始化构造函数中: String(const char *s) { Length=strlen(s); Sp=new char[Length +1]; strcpy(Sp,s); } 形参为字符串指针变量s,为了防止在构造函数内修改实参字符串的值,特在形参类型前加关键词const,表示在构造函数内,s所指字符串是不能修改的。初始化构造函数体内,先用字符串函数strlen求出字符串s的长度,并赋给Length。然后用new运算符动态建立字符数组,将字符数组首地址赋给字符串指针Sp,最后用字符串拷贝函数strcpy将字符串s拷贝到Sp所指字符串中。完成String类对象数据成员Length与Sp的初始化工作。 (2)字符串赋值“=”运算符重载成员函数中: void String::operator=(String &s) { if (Sp) delete []Sp; Length=s.Length; if (s.Sp) { Sp=new char [Length+1]; strcpy(Sp,s.Sp); } else Sp=0;