运算符重载 潘荣江 panrj@sdu.edu.cn 山东大学
内容 运算符重载为类的成员函数 运算符重载为类的友元函数 双目运算符的重载 单目运算符的重载 流运算符的重载 转换构造函数 类型转换函数
复习: 类(class) #include<iostream> using namespace std; class Complex //定义Complex类 { public: Complex(){real=0; imag=0;} //定义构造函数 Complex(double r, double i){real=r;imag=i;} //构造函数重载 Complex complex_add(Complex &c2); //声明复数相加函数 void display(); //声明输出函数 private: double real; //实部 double imag; //虚部 };
Complex Complex∷complex_add(Complex &c2) //定义复数相加函数 c.real=real+c2.real; c.imag=imag+c2.imag; return c; } void Complex∷display() //定义输出函数 { cout<<"("<<real<<","<<imag<<"i)"<<endl; } int main() { Complex c1(3,4),c2(5,-10),c3; //定义3个复数对象 c3=c1.complex_add(c2); //调用复数相加函数 cout<<"c1="; c1.display(); //输出c1的值 cout<<"c2="; c2.display(); //输出c2的值 cout<<"c1+c2="; c3.display(); //输出c3的值 return 0; } 运行结果: c1=(3,4i) c2=(5,-10i) c1+c2=(8,-6i)
函数重载 (function overloading) 函数重载是指完成不同功能的函数可以具有相同的函数名。 C++的编译器根据函数的实参来确定应该调用哪一个函数。 1、定义的重载函数必须具有不同的参数个数,或不同的参数类型。编译系统根据不同的参数去调用不同的重载函数,实现不同的功能。 2、仅返回值不同时,不能定义为重载函数。 int fun(int a, int b) { return a+b; } void main(void) { cout<<fun(3,5)<<endl; cout<<fun(5)<<endl; } 8 int fun (int a) { return a*a; } 25
系统自动识别int、float等数据类型的+ 运算符重载(operator overloading) int sum,a=3,b=2; (int)=(int) + (int) sum=a+b; 系统自动识别int、float等数据类型的+ float add, x=3.2, y=2.5; add=x+y; (float)=(float) + (float) Complex c1(3,4), c2(5,-10), c3; //定义3个复数对象 c3=c1 + c2; //8-6i 编译系统中的运算符“+”本身不能做Complex的“+”运算,必须重新定义“+”运算符,这种重新定义的过程称为运算符的重载。
运算符重载实现两个复数相加 两对象+,必须重新定义+ 运算符重载赋予已有的运算符多重含义。C++通过重新定义运算符,使它能够用于特定的对象,执行特定的功能
//也可以利用无名对象 Complex Complex∷operator+(Complex &c2) //定义重载运算符+的函数 { return Complex(real+c2.real, imag+c2.imag); } 将运算符+重载为类的成员函数后, C++编译系统将程序中的表达式 c1+c2 解释为 c1.operator+(c2) //其中c1和c2是Complex类的对象,即以c2为实参调用c1的运算符重载函数operator+(Complex &c2), 得到两个复数之和。 c3 = c1+c2; // 可以 c3 = 3 + c2; //能这样做吗? c3 = Complex(3,0) + c2;
运算符的重载体现了OOP技术的多态性,且同一运算符根据不同的运算对象可以完成不同的操作。 为了重载运算符,必须定义一个函数,告诉编译器,遇到这个重载运算符就调用该函数,由这个函数来完成该运算符应该完成的操作,这种函数称为运算符重载函数,它通常是类的成员函数或者是友元函数。运算符的操作数通常也应该是类的对象。 运算符的重载体现了OOP技术的多态性,且同一运算符根据不同的运算对象可以完成不同的操作。 运算符重载对C++有重要的意义。 本来C++ 提供的运算符只能用于C++的标准数据类型,不能用于用户定义的类对象,影响了类和对象的使用。 C++不是为类对象另外定义一批新的运算符,而是允许重载现有的运算符,使这些简单易用、众所周知的运算符能够直接用于类对象。运算符重载使C++具有更强大的功能、更好的可扩充性和适应性。
A operator + (A &); 运算符重载函数的格式 { 函数体 } 运算的对象 关键字 函数名 运算的对象 返回类型 A operator + (A &); //重载了类A的“+”运算符 其中:operator是定义运算符重载函数的关键字,它与其后的运算符一起构成函数名。
利用函数完成了加法运算 没有使用运算符重载的例子 class A { int i; public: A(int a=0) { i=a; } void Show(void){ cout<<"i="<<i<<endl; } A AddA(A &a) //利用函数进行对象之间的运算 { return A(i+a.i); } }; void main(void) { A a1(10),a2(20),a3; a1.Show (); a2.Show (); // a3=a1+a2; //不可直接运算 a3=a1.ddA(a2); //调用专门的功能函数 a3.Show (); } 利用函数完成了加法运算
运算符重载的例子 class A { int i; public:A(int a=0){ i=a; } void Show(void){ cout<<"i="<<i<<endl; } A AddA(A &a) //利用函数进行对象之间的运算 { return A(i+a.i); } A operator +(A &a) //重载运算符+ { A t; t.i=i+a.i; return t; } }; void main(void) { A a1(10),a2(20),a3; a1.Show (); a2.Show (); a3=a1+a2; //重新解释了加法,可以直接进行对象的运算 a3=a1.AddA(a2); //调用专门的功能函数 a3.Show (); } 相当于a3=a1.operator+(a2)
A AddA(A &a) { return A(i+a.i); } A operator +(A &a) { A t; t.i=i+a.i; 重载运算符与一般函数的比较: 相同:1)均为类的成员函数;2)实现同一功能 返回值 函数名 形参 返回值 函数名 形参列表 A AddA(A &a) { return A(i+a.i); } A operator +(A &a) { A t; t.i=i+a.i; return t; } 函数调用: A3=a1.AddA(a2); 函数调用: 由对象a1调用 a3=a1+a2; a3=a1.operator+(a2); 由对象a1调用
重载运算符的规则 只能对C++中已有的运算符进行重载。 在C++中允许重载的运算符如下。
C++中不能重载的运算符只有5个:. (成员访问运算符). (成员指针访问运算符) ∷ (域运算符) sizeof (长度运算符) 前两个运算符不能重载是为了保证访问成员的功能不能被改变。 域运算符和sizeof运算符的运算对象是类型而不是变量或一般表达式,不具重载的特征。 重载不能改变运算符的优先级、结合性、运算对象(即操作数)的个数。 重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数。
r4=r1+r2+r3; (r1+r2); (r1+r2)+r3; r4=r1+(r2+r3); (r2+r3); r1+(r2+r3); class room{ float Length; float Wide; public: room(float a=0.0,float b=0.0){ Length=a; Wide=b; } void Show(void){cout<<"Length="<<Length<<'\t'<<"Wide="<<Wide<<endl;} void ShowArea(void){ cout<<"Area="<<Length*Wide<<endl; } room operator+(room &);//重载运算符+,函数原型 }; room room::operator + (room &r) //重载运算符函数 { room rr; rr.Length =Length+r.Length; rr.Wide =Wide+r.Wide ; return rr; } void main(void) { room r1(3,2),r2(1,4), r3,r4; r1.Show (); r2.Show (); r3=r1+r2; r3.Show (); r4=r1+r2+r3; r4.Show (); r4=r1+r2+r3; (r1+r2); (r1+r2)+r3; r4=r1+(r2+r3); (r2+r3); r1+(r2+r3); 运算符的优先级和结合律是不能改变的
重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。 用于类对象的运算符一般必须重载,但有两个运算符不需用户重载。 ①赋值运算符(=)可以用于每一个类对象,利用它在同类对象之间相互赋值。 ②地址运算符&也不必重载,它能返回类对象在内存中的起始地址。 应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。
运算符重载函数作为类成员函数 当用成员函数实现运算符的重载时,运算符重载函数的参数只能有二种情况:没有参数或带有一个参数。 对于只有一个操作数的运算符(如++),在重载这种运算符时,通常不能有参数; 对于有二个操作数的运算符,只能带有一个参数。这个参数可以是对象、对象的引用或其它类型的参数。
运算符重载为类成员函数时,是由一个操作数调用函数,函数的实参只有一个或没有。 A a ,b , c; c=a+b; 实际上是c=a.operator+(b); c=++a; 实际上是c=a.operator++( ); c+=a; 实际上是c.operator+=( a ); 用成员函数实现运算符的重载时,运算符的左操作数为当前对象,这是一个隐含的参数,要用到隐含的this指针。 运算符重载函数不能定义为静态的成员函数,因为静态的成员函数中没有this指针。
没有返回值,函数类型为void。 class A { int i; public:A(int a=0){ i=a; } void Show(void){ cout<<"i="<<i<<endl; } A operator +(A &a) //重载运算符+ { A t; t.i=i+a.i; return t; } void operator+=(A &a) { i=i+a.i; } }; void main(void) { A a1(10),a2(20),a3; a1.Show (); a2.Show (); a3=a1+a2; a1+=a2; a3.Show (); } 没有返回值,函数类型为void。 相当于a3=a1.operator+(a2) 相当于a1.operator+=(a2)
运算符重载为类的友元函数 友元函数是在类外的普通函数,与一般函数的区别是可以调用类中的私有或保护数据。 将运算符的重载函数定义为友元函数,参与运算的对象全部成为函数参数。 A a ,b , c; c=a+b; 实际上是 c=operator+(a, b); c=++a; 实际上是 c=operator++(a); c+=a; 实际上是 operator+=(c, a);
对单目运算符,友元函数有一个参数。 对双目运算符,友元函数有2个参数。 格式为: friend <类型说明> operator<运算符>(<参数表>) {......} c=a+b; // c=operator+( a, b) friend A operator + (A &a, A &b) {.....}
}
运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。 只有在极少的情况下才使用既不是类的成员函数也不是友元函数的普通函数,原因是普通函数不能直接访问类的私有成员。 如果将运算符重载函数作为成员函数,可以通过this指针自由地访问本类的数据成员,少写一个函数的参数。但必须要求运算表达式第一个参数(即运算符左侧的操作数)是一个类对象,而且与运算符函数的类型相同,必须通过类的对象去调用该类的成员函数。 如:表达式c1+c2中第一个参数c1是Complex类对象,这是正确的。如果c1不是Complex类,就无法通过隐式this指针访问Complex类的成员了。
如想将一个复数和一个整数相加,如c1+i, 可以将 运算符重载函数作为成员函数,如下面的形式: Complex Complex∷operator+(int i) //运算符重载函数作为Complex 类的成员函数 {return Complex(real+i,imag);} 注意在表达式中重载的运算符“+”左侧应为Complex类的对象,如 c3=c2+i; 不能写成 c3=i+c2; //运算符“+”的左侧不是类对象,编译出错 如果出于某种考虑,要求在使用重载运算符时运算符左侧的操作数是整型量(如表达式i+c2, 运算符左侧的操作数i是整数),这时无法利用前面定义的重载运算符,因为无法调用i.operator+函数。 如果运算符左侧的操作数属于C++标准类型(如int)或是一个其他类的对象,则运算符重载函数不能作为成员函数,只能作为非成员函数。如果函数需要访问类的私有成员,则必须声明为友元函数。
在Complex类中声明: friend Complex operator+(int i,Complex &c); //第一个参数可以不是类对象 在类外定义友元函数: Complex operator+(int i, Complex &c) //运算符重载函数不是成员函数 {return Complex(i+c.real,c.imag);} 将双目运算符重载为友元函数时,在函数的形参表列中必须有两个参数,不能省略,形参的顺序任意,不要求第一个参数必须为类对象。但在使用运 算符的表达式中,要求运算符左侧的操作数与函数第一个参数对应,运算符右侧的操作数与函数的第二个参数对应。 c3=i+c2; //正确,类型匹配 c3=c2+i; //错误,类型不匹配 数学上的交换律在此不适用。如果希望适用交换律,则应再重载一次运算符“+”。 Complex operator+(Complex &c, int i) //此时第一个参数为类对象 { return Complex(i+c.real,c.imag); } 这样,使用表达式i+c2和c2+i都合法。
C++规定,赋值运算符=、下标运算符[]、函数调用运算符()、成员运算符-> 必须定义为类的成员函数。 流插入运算符“<<”、流提取运算符“>>”、类型转换运算符不能定义为类的成员函数,只能作为友元函数。 一般将单目运算符和复合运算符重载为成员函数。 一般将双目运算符重载为友元函数。
双目运算符的重载 双目运算符(或称二元运算符)是C++中最常用的运算符。双目运算符有两个操作数,通常在运算符的左右两侧,如3+5,a=b,i<10等。 如果要重载双目运算符B 为类成员函数,使之能够实现表达式 oprd1 B oprd2,其中 oprd1 为A 类对象,则 B 应被重载为 A 类的成员函数,形参类型应该是 oprd2 所属的类型。 经重载后,表达式 oprd1 B oprd2 相当于 oprd1.operator B(oprd2)
指导思想: 先搭框架,逐步扩充,由简到繁,最后完善。
单目运算符的重载 只有一个操作数的运算符为单目运算符,常用的有: !a, -b, &c, *p ,++,--。 A a; ++a; a++; A a, b; b=++a; b=a++; 虽然运算后对象a的值一致,但先自加或后自加的函数的返回值不一致,必须在重载时予以区分。
A a, b; b=++a; b=a++; A operator ++( ){ .... } ++为前置运算时,运算符重载函数的一般格式为: <type> operator ++( ) { ...... } ++为后置运算时,运算符重载函数的一般格式为: <type> operator ++(int) A a, b; b=++a; b=a++; A operator ++( ){ .... } A operator ++(int){ .... }
例 有一个Time类,包含数据成员minute(分)和sec(秒),模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算。要求输出分和秒的值。 #include <iostream> using namespace std; class Time { public: Time( ){minute=0;sec=0;} //默认构造函数 Time(int m,int s):minute(m),sec(s){ } //构造函数重载 Time operator++( ); //声明前置自增运算符“++”重载函数 Time operator++(int); //声明后置自增运算符“++”重载函数 void display( ){ cout<<minute<<″:″<<sec<<endl; } //定义输出时间函数 private: int minute; int sec; };
Time Time∷operator++( ) //定义前置自增运算符“++”重载函数 { if(++sec>=60) { sec-=60; ++minute; } return *this; //返回自加后的当前对象 } Time Time∷operator++(int) //定义后置自增运算符“++”重载函数 { Time temp(*this); sec++; if(sec>=60) { sec-=60; ++minute; } return temp; //返回的是自加前的对象 }
int main( ) { Time time1(34,59),time2; cout<<″ time1 :″; time1.display( ); ++time1; cout<<″++time1:″; time1.display( ); time2=time1++; //将自加前的对象的值赋给time2 cout<<″time1++:″; time1.display( ); cout<<″ time2 :″; time2.display( ); //输出time2对象的值 }
A operator ++(A a, int){ .... } ++为前置运算时,友元运算符重载函数的一般格式为: A operator ++(A &a) { ......;} ++为后置运算时,友元运算符重载函数的一般格式为: A operator ++(A &a, int) A a, b; b=++a; b=a++; A operator ++( A a ){ .... } A operator ++(A a, int){ .... }
相当于a3=operator++(a1,int) class A { int i; public: A(int a=0) { i=a; } void Show(void) { cout<<"i="<<i<<endl; } A operator++(A &a){ a.i++; return a;} A operator++(A &a, int n) { A t; t.i=a.i; a.i++; return t; } }; void main(void) { A a1(10),a2,a3; a2=++a1; a3=a1++; a2.Show(); a3.Show (); } 相当于a2=operator++(a1) 相当于a3=operator++(a1,int)
流运算符的重载 C++的流插入运算符“<<”和流提取运算符“>>”是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream。 cin和cout分别是istream类和ostream类的对象。在类库提供的头文件中已经对“<<”和“>>”进行了重载,作为流插入运算符和流提取运算符,能用来输出和输入C++标准类型的数据,用#include <iostream>包含到自己的程序文件中。 用户自己定义的类型的数据,不能直接用“<<”和“>>”来输出和输入。如果想用它们输出和输入自己声明的类型的数据,必须对它们重载。对“<<”和“>>”重载的函数形式如下: istream & operator >> (istream &,自定义类 &); ostream & operator << (ostream &,自定义类 &); 重载“>>”的函数的第一个参数和函数的类型都必须是istream&类型,第二个参数是要进行输入操作的类。 重载“<<”的函数的第一个参数和函数的类型都必须是ostream&类型,第二个参数是要进行输出操作的类。 只能将重载“>>”和“<<”的函数作为友元函数或普通的函数,而不能将它们定义为成员函数。(why?)
用重载的“<<”输出复数。 #include <iostream> using namespace std; class Complex {public: Complex( ){real=0;imag=0;} Complex(double r,double i) {real=r;imag=i;} Complex operator + (Complex &c2); //运算符“+”重载为成员函数 friend ostream& operator << (ostream&,Complex&); //“<<”重载为友元函数 private: double real; double imag; }; Complex Complex∷operator + (Complex &c2) //定义运算符“+”重载函数 { return Complex(real+c2.real,imag+c2.imag);} ostream& operator << (ostream& output, Complex& c) //定义运算符“<<”重载函数 { output<<″(″<<c.real<<″+″<<c.imag<<″i)″<<endl; return output; }
int main( ) { Complex c1(2,4),c2(6,10),c3; c3=c1+c2; cout<<c3; return 0; } 运行结果为:(8+14i) 编译系统把“cout<<c3”解释为operator<<(cout,c3) return output的作用是什么? 返回cout的当前值,以便连续输出 。output是ostream类的对象,它是实参cout的引用,也就是cout通过传送地址给output,它们二者共享同一段存储单元,或者说output是cout的别名。return output就是return cout,将输出流cout的现状返回,即保留输出流的现状。 cout<<c3<<c2; (cout<<c3)<<c2;
增加重载流提取运算符“>>”,用cin>>输入复数,用cout<<输出复数。 #include <iostream> using namespace std; class Complex {public: friend ostream& operator << (ostream&,Complex&); //声明重载运算符“<<” friend istream& operator >> (istream&,Complex&); //声明重载运算符“>>” private: double real; double imag; }; ostream& operator << (ostream& output,Complex& c) //定义重载运算符“<<” { output<<″(″<<c.real<<″+″<<c.imag<<″i)″; return output; } istream& operator >> (istream& input,Complex& c) //定义重载运算符“>>” { cout<<″input real part and imaginary part of complex number:″; input>>c.real>>c.imag; return input; }
int main( ) { Complex c1,c2; cin>>c1>>c2; cout<<″c1=″<<c1<<endl; cout<<″c2=″<<c2<<endl; return 0; } 运行情况如下: input real part and imaginary part of complex number: 3 6↙ input real part and imaginary part of complex number: 4 10↙ c1=(3+6i) c2=(4+10i)
虚部如果是负数,就不理想。 input real part and imaginary part of complex number:3 6↙ input real part and imaginary part of complex number:4 -10↙ c1=(3+6i) c2=(4+-10i) 可对程序作必要的修改,将重载运算符“<<”函数修改如下: ostream& operator << (ostream& output,Complex& c) { output<<″(″<<c.real; if(c.imag>=0) output<<″+″; //虚部为正数时,在虚部前加“+”号 output<<c.imag<<″i)″<<endl; //虚部为负数时,在虚部前不加“+”号 return output; } 这样,运行时输出的最后一行为c2=(4-10i)。
标准类型数据间的转换 有些转换是由C++编译系统自动完成的,用户不需干预。这种转换称为隐式类型转换。 int i = 6; i = 7.5 + i; C++还提供显式类型转换,在程序中指定将一种指定的数据转换成另一指定的类型,其形式为 类型名(数据) 如 int(89.5), 其作用是将89.5转换为整型数89
转换构造函数 转换构造函数(conversion constructor function)的作用是将一个其他类型的数据转换成一个类的对象。 •默认构造函数。 Complex( ); //没有参数 •用于初始化的构造函数。 Complex(double r,double i); //形参表列中一般有两个以上参数 •用于复制对象的复制构造函数。 Complex (Complex &c); //形参是本类对象的引用 •转换构造函数。转换构造函数只有一个形参,如 Complex(double r) {real=r; imag=0;} 其作用是将double型的参数r转换成Complex类的对象,将r作为复数的实部,虚部为0。 用户可以根据需要定义转换构造函数,在函数体中告诉编译系统怎样去进行转换。在类体中,可以有转换构造函数,也可以没有转换构造函数,视需要而定。以上几种构造函数可以同时出现在同一个类中,它们是构造函数的重载。编译系统会根据建立对象时给出的实参的个数与类型 选择形参与之匹配的构造函数。
在该类的作用域内可以用以下形式进行类型转换: 类名(指定类型的数据) 就可以将指定类型的数据转换为此类的对象。 Complex c1(3.0); Complex c2= Complex(3.0); //先建立一个无名对象,然后复制 Complex c3= 3.0; Complex c = c1 + Complex(3.0); 不仅可以将一个标准类型数据转换成类对象,也可以将另一个类的对象转换成类对象。 如可以将一个学生类对象转换为教师类对象,可以在Teacher类中写出下面的转换构造函数: Teacher(Student& s) { num=s.num; strcpy(name,s.name); sex=s.sex; } 但应注意: 对象s中的num,name,sex必须是公用成员,否则不能被类外引用。
类型转换函数 类型转换函数是在类中定义一个成员函数,将类的对象转换为另外一种类型的数据。 利用转换函数将类A的对象a转换成某种数据类型 class A { float x, y; public: A(float a, float b){ x=a; y=b; } }; void main(void) { A a(2,3); cout<<a<<endl; } 利用转换函数将类A的对象a转换成某种数据类型 错误!类的对象不能直接输出
A float 1. 转换函数必须是类的成员函数,不能是友元函数。 格式为: ClassName :: operator <type>( ) {.........} 类名 关键字 欲转换类型 具体的转换算法 2. 转换函数的调用是隐含的,没有参数。转换函数的操作数是对象。 A :: operator float ( ) { return x+y; } 转换算法自己定义
class A { int i; public:public: A(int a=0) { i=a; } void Show(void) { cout<<"i="<<i<<endl; } operator int( ){ return i; } }; void main(void) { A a1(10), a2(20); cout<<a1<<endl; // 可以直接输出c,因为已经进行类型转换 cout<<a2<<endl; }
class Complex{ float Real,Image; public: Complex(float real=0, float image=0) { Real=real; Image=image; } void Show(void) {cout<<"Real="<<Real<<'\t'<<"Image="<<Image<<endl; } operator float(); //成员函数,定义类转换 Complex->float }; Complex::operator float () { return Real*Real+Image*Image;} void main(void) { Complex c(10,20); c.Show (); cout<<c<<endl;//可以直接输出c,因为已经进行类型转换 }
赋值运算符与赋值运算符重载 “=” 同类型的对象间可以相互赋值,等同于对象的各个成员的一一赋值。 A a(2,3), b; b=a; 但当对象的成员中使用了动态的数据类型时(用new开辟空间),就不能直接相互赋值,否则在程序的执行期间会出现运行错误。
A(char *s ){ ps =new char [strlen(s)+1]; strcpy(ps,s);} class A{ char *ps; public: A( ){ ps=0;} A(char *s ){ ps =new char [strlen(s)+1]; strcpy(ps,s);} ~A( ){ if (ps) delete [] ps;} void Show(void) { cout<<ps<<endl;} }; void main(void ) { A s1("China!"),s2("Computer!"); s1.Show(); s2.Show(); s2=s1; } s1 ps “China” s2 ps "Computer" s2.ps=s1.ps //相当于 s2.ps=s1.ps; 首先析构s2 接着析构s1出错
这时,利用编译系统的默认赋值无法正确运行程序,必须重载赋值运算符“=”,即重新定义“=”。 格式为: <函数类型> <ClassName>::operator=(<参数表>) 赋值运算符必须重载为成员函数。 函数名 函数参数 成员函数作用域 A A:: operator = (A &a) 左操作符调用右操作符 函数返回值类型 b.operator=(a); b=a;
class A{ char *ps; public: A( ){ ps=0;} A(char *s ){ ps =new char [strlen(s)+1]; strcpy(ps,s);} ~A( ){ if (ps) delete [] ps;} void Show(void) { cout<<ps<<endl;} A& operator=(A &b); }; void main(void ) { A s1("China!"),s2("Computer!"); s1.Show(); s2.Show(); s2=s1; } 重新定义“=”
A & A::operator = ( A &b)//重载赋值运算符 { if ( ps ) delete [ ] ps; if ( b.ps) { ps = new char [ strlen(b.ps)+1]; strcpy( ps, b.ps); } else ps =0; return *this; s2=s1; s2.operator=(s1); s1 ps “China” s2 ps “China” “Computer” 返回同种类型的引用适合于连等。 s3=s2=s1;
class A{ char *ps; public: A( ){ ps=0;} A(char *s ){ ps =new char [strlen(s)+1]; strcpy(ps,s); } ~A( ){ if (ps) delete[] ps;} char *GetS( ) {return ps;} A & operator = ( A &b);//重载赋值运算符 }; A &A::operator = ( A &b)//重载赋值运算符 { if ( ps ) delete [ ] ps; if ( b.ps) { ps = new char [ strlen(b.ps)+1]; strcpy( ps, b.ps); } else ps =0; return *this; } void main(void ) { A s1("China!"),s2("Computer!"); s2=s1; cout <<"s1= "<< s1.GetS()<<'\t'; cout <<"s2= "<< s2.GetS()<<'\n'; 重新开辟内存 s2.ps重新开辟内存,存放“China”