Download presentation
Presentation is loading. Please wait.
1
第9章 重载
2
1.重载的概念 (1) int abs(int x){ return (x>=0 ? x: -x ); }
C++语言提供了一种机制,使得对于不同的输入参数,使用统一的函数名(如例9.1的abs())定义各种不同输入参数时的实现版本,由编译程序根据函数参数的不同而选择使用相应的实现代码。这就叫做函数的重载。 1.重载的概念 (1) 例9.1 求绝对值函数abs( )的重载 int abs(int x){ return (x>=0 ? x: -x ); } double abs(double x){ lone abs(lone x){ 表面上,似乎这三个函数的代码相同。实际上编译时产生的代码是不同的,程序运行时在内存中的存放位置也是不同的。 另外,C++中由于引入了大量扩展数据类型,特别是通过类的定义引入的各种外部类型,希望能够用比较简洁的、统一的形式来书写这些自定义类型的表达式。比如,对于一个复数类Complex的对象C1和C2,若想不用Complex_ADD(C1,C2), 而用C1+C2的形式来书写这两个对象的求和式,这就需要使“+”运算符重载复数Complex类求和运算。
3
重载的概念 (2) 重载的概念 (2) 重载分为函数重载和运算符重载。 函数重载由参数形式区分同名函数的不同版本。
构造函数重载是函数重载的主要应用之一,它为对象创建提供了灵活方便的内部状态初始化手段。 运算符重载使自定义抽象数据类型能像基本数据类型一样用系统已定义的运算符来书写表达式,这就使得对象的使用像内部变量一样自然和方便,因而带来了更加自然的系统可扩展性。 重载的概念 (2)
4
2.函数重载 函数重载就是用同一个标识符命名语义相近的一组函数。函数重载作为一种符号抽象工具。程序员可以利用这个工具定义一个抽象函数,其函数名描述一组函数功能的共同点,以减少由于大量符号定义带来的记忆负担。值得注意的是,C++语言并没有提供重载函数之间的任何约束,如果用相同的名字定义互不相关的函数,只会产生增加程序复杂性的负面效果。
5
2.1 函数重载的区分机制 重载函数靠参数不同而区分不同调用版本。决定参数是否相同有参数个数、参数顺序、参数类型等要素。
2.1 函数重载的区分机制 重载函数靠参数不同而区分不同调用版本。决定参数是否相同有参数个数、参数顺序、参数类型等要素。 如length ()函数的重载说明: int length (int x); int length (int x, int y); double length (double x1, double x2, double y1, double y2); 这三个函数,由于它们的函数名相同,参数不同而成为重载函数,与它们返回值类型相同并无关系。 1.用参数区分函数重载的不同调用版本 int sum (int x, int y);和 double sum (int a, int b); 这两个函数不是重载函数,因为它们参数个数和类型都相同,尽管它们的返回值类型不同、形式参数名也不同。编译程序认为它们是对一个函数的重新定义(override) 另外不同的参数传递方式也无法区分重载函数,如: int func1(int value); int func1(int &value); 不能作为重载函数。
6
例9.2 试分析下面的程序及调用结果,并说明get_area()函数是否属于函数重载。
void main() { point p1(3,7); circle c1(2,3,4),c2(5,1,4); cout<<c1.get_area()<<endl; cout<<p1.get_area()<<endl; cout<<c2.get_area()<<endl; cout<<c2.point::get_area()<<endl; } #include<iostream.h> class point{ double x,y; public: point(double a, double b){ x=a; y=b; } double get_area() { return 0; } }; class circle: public point{ int r; circle(int rad, int a, int b):point(a,b) { r=rad; } {return *r*r;} 运行结果: 78.54 本例实际上也是派生类中同名函数的重定义。可以简单地认为,加上对象名或类名前缀后,c1.get_area()和p1.get_area()不再被看作同名函数。
7
2.const关键字可以被用于参与对重载函数的区分
常成员函数: 在一个类中使用const关键字说明的成员函数,称为常成员函数。常成员函数说明格式如下: 函数类型 函数名(<参数表>)const ; 其中,const是加在函数说明后面的类型修饰符,它是函数说明的一个组成部分,因此,在函数的实现部分也要带const关键字。常成员函数不更新对象的数据成员,也不能调用该类中其它没有用const修饰的成员函数。
8
例9.3 常成员函数举例。 class M{ int m1,m2; public:
M(int x,int y){ m1 = x ; m2 = y ;} void print ( ) { cout<<m1<<”,”<<m2<<endl; } void print ( ) const ; }; void M::print ( ) const { cout<<m1+m2<<endl; } void main ( ){ M a (5,4); a.print ( ) ; const M b(8,7); b.print ( ) ; } 程序运行结果: 5,4 15 在类M的成员中,说明了两个同名的成员函数print(),但它们的类型不同,如下所示: void print ( ) ; void print ( ) const ; 这是重载的成员函数。表达式:a.print()将调用成员函数:void print ( ); 而表达式:b.print ( ) 将调用成员函数:void print ( ) const ;
9
3.函数重载的二义性 函数缺省参数是函数重载的一种特殊形式。但带缺省参数的函数重载时有可能发生二义性错误。
例:#include(iostream.h) #include(math.h) int main( ){ int function1(int x, int y){ return sqrl(x*x+y*y); } int function1(int x=3, int y=5){return x*y;} 则调用:function1(1,2) 、function1(7)和function1( )都能分别得到正确的结果。 但是若定义: int function2(int x){return x*x;} int function2(int x, int y=5){return x*y;} 调用 funtion2(3),将产生二义性,编译时出错
10
2..2 构造函数重载 构造函数重载是C++应用函数重载最多的地方。C++允许为一个类定义多个构造函数。除了保证类数据成员有效性以外,多构造函数为用不同形式初始化对象带来了极大的方便。
11
例9.4 时间类的构造函数重载。1 #include<iostream.h> #include<stdlib.h>
class Time{ int hh, mm, ss; public: Time(); Time(int hour, int inute, nt second); Time(int second); Time(char *str); void print() { cout<<hh<<":"<<mm<<":"<<ss<<"\n"; } };
12
例9.4 时间类的构造函数重载。2 Time::Time(){ hh=0; mm=0; ss=0;}
Time::Time(int hour, int minute, int second) { if (hour<0||minute<0||second<0) { hh=0; mm=0; ss=0; cout<<"Illegal initical value! Time variant don't allowed under zero."<<endl; } else{ if (second>59) { minute=minute+ second/60; second= second%60; } if (minute >59) { hour = hour + minute /60; minute = minute %60; } if (hour >23) hour = hour%24; hh=hour; mm=minute; ss=second; }
13
例9.4 时间类的构造函数重载。3 Time::Time(int second) { hh=0;mm=0; if (second<0)
{ ss=0; cout<<"Illegal input value! Time variant don't allowed under zero. ”; cout<<endl; } else{ if (second>59) mm=second/60; ss=second%60; if (mm>59) hh=mm/60; mm=mm%60; if (hh>23) hh=hh%24; }
14
例9.4 时间类的构造函数重载。4 Time::Time(char *string) { char *str=new char[3];
str[0]=string[0]; str[1]=string[1]; str[2]='\0'; hh=atoi(str); str[0]=string[3]; str[1]=string[4]; mm=atoi(str); str[0]=string[6]; str[1]=string[7]; ss=atoi(str); delete str; } void main(){ Time t1,t2(100,100,100),t3(3690),t4("18:56:34"); cout<<"t1 : ";t1.print(); cout<<"t2 : ";t2.print(); cout<<"t3 : ";t3.print(); cout<<"t4 : ";t4.print(); } 程序运行结果: t1 : 0:0:0 t2 : 5:41:40 t3 : 1:1:30 t4 : 18:56:34 在本例中构造函数重载了四次。
15
拷贝初始化构造函数是一种特殊的构造函数,具有一般构造函数的所有特性,其形参是本类对象的引用,功能是用一个已知的对象去初始化一个被创建的同类对象。典型情况是,将参数代表的对象的数据成员的值拷贝给正在创建的另一个同类的对象。 用户可以根据自己实际问题的需要定义特定的拷贝初始化构造函数,以实现同类对象之间数据成员的传递。 C++规定每个类都必须有一个拷贝初始化构造函数,如果用户没有为一个类定义拷贝初始化构造函数,则系统就会为该类自动产生一个缺省拷贝初始化构造函数。缺省拷贝初始化构造函数将一个已定义对象的所有数据成员拷贝给新对象。 当被拷贝对象的数据成员中含有指向其它类对象的指针时,这种拷贝方式形成的对象在释放时有产生内存垃圾及指针别名等问题,此时就应该由用户定义拷贝构造函数来处理。 拷贝初始化构造函数的定义格式如下: 类名::构造函数名(const 类名 &引用名) { … // 函数体 } 拷贝构造函数名的参数是一个本类对象的常引用。所谓常引用就是用const定义的引用。const是一个类型修饰符,被它修饰的对象是一个不能被更新的常量。作为常引用的实参对象的成员,在函数调用过程中不会无意中被修改。 2.3 拷贝初始化构造函数
16
例9.5 拷贝初始化构造函数的定义和调用。1 # include<iostream.h> class Point{
double x , y ; public: Point (double a , double b) {x = a ; y = b ; cout<< “Constructor called . “<<endl ;} // 普通构造函数 Point (const Point &p); // 拷贝初始化构造函数 ~Point ( ) {cout<< “The destructer is called . “<<endl ;} // 析构函数 double GetX ( ) {return x ;} double GetY ( ) {return y ;} void Print ( ) {cout<<”The point is : (“<< x <<”, ”<< y<<”)” <<endl;} };
17
例9.5 拷贝初始化构造函数的定义和调用。 2 Point :: Point (const Point &p ) // 拷贝初始化构造函数的定义 { x = p.x ; y = p.y ; cout<<”Copy initialization Constructor called .”<<endl ; } void main ( ) { Point p1(3.14 , 4.2) ; // 定义对象point1,并指定初始化参数为:3.14 , 4.2 Point p2(p1); // 定义对象p2,指定初始化参数为对象p1 p1.Print( ) ; p2.Print( ); 程序输出: Constructor called. Copy initialization Constructor called . The point is : (3.14, 4.2) The destructer is called .
18
拷贝初始化构造函数在以下三种情况下都会被调用:
当用类的一个对象去初始化该类的另一个对象时。如例9.5中:用对象p1去初始化对象p2。 (2) 如果函数的形参是类的对象,调用函数进行形参和实参结合时。例如: void fun( Point p) { cout<<p.GetX( )<<”,”<<p.GetY( )<<endl ; } void main( ) { Point px (2.8, 3.5); fun (px ) ; } 在调用fun()函数时,对象px是实参,要用它来初始化被调用函数的形参p,这时需要调用拷贝构造函数,完成实参对象与形参对象进行数据传递的工作 (3) 当对象作为函数的返回值时。例如: Point g( ) { Point A(2.8, 3.5); return A ; } 执行返回语句return A;时,系统将用对象A来初始化一个匿名对象,这时需要调用拷贝构造函数。 }
19
例9.6点类及拷贝初始化构造函数测试程序1 # include<iostream.h> class Point{
double x,y; public: Point (double a , double b) {x = a ; y = b ; cout<< "Constructor called."<<endl ;} Point ( const Point &p); // 拷贝初始化构造函数 ~Point ( ) {cout<< "The destructor is called. "<<endl ;} double GetX( ) {return x;} double GetY( ) {return y;} void Print ( ) {cout<<"The point is : ("<< x <<","<< y<<")" <<endl;} };
20
例9.6点类及拷贝初始化构造函数测试程序2 Point :: Point ( const Point &p ) // 拷贝初始化构造函数的定义 { x = p.x ; y = p.y ; cout<<"Copy initialization Constructor called."<<endl; } Point fun( Point p) { double a , b ; a = p.GetX( ) + 5 ; b = p.GetY( ) + 10 ; Point R(a,b); return R; } void main ( ) { Point p1(3.14 , 4.28) , p2(0,0); Point p3(p1); // 定义对象p3, //并指定初始化参数为对象p1 p2 = fun(p3); p1.Print( ) ; p2.Print( ); p3.Print( ); } 程序执行结果如下: Constructor called. Copy-initialization Constructor called. The destructor is called. The point is : (3.14,4.28) The point is : (8.14,14.28)
21
3 运算符重载 3.1 运算符重载的概念 一个数据类型的定义包括一个值集和一个作用于该值集的操作集。C++在提供内部基本数据类型的同时提供了许多预定义的运算符,用于各种表达式中。如算术运算符、逻辑运算符、比较运算符、取值、取地址、括号等等。 基本数据类型上的运算符,其语义等价为一个函数,如声明x, y为int或double等基本类型变量,那么表达式x+y可以理解为 函数add(x, y) 或+(x, y) ,显然,使用前一种形式比使用后两种形式使表达式的书写更简洁、更符合日常习惯。 在一个类中定义的运算符成员函数称类成员运算符,在类之外定义的运算符函数通常使用类的友元函数的形式,称为友元运算符。
22
3.2类成员运算符重载 运算符重载的基本语法形式: 类型 类名::operator 运算符(<参数表>) //运算符函数头 {
……; //运算符函数体 } 若将定义头中“operator 运算符”部分用普通函数名替代,则与普通函数定义头形式完全相同。operator 是专门用于定义重载运算符的系统保留字。在下面的例子中还可以看到,重载过的运算符还可以再重载。
23
类成员运算符重载的实现 重载一元运算符时参数表为空,当前对象作为运算符的单操作数(在函数体中用this指针访问);
重载二元运算符时参数表中有一个操作数,当前对象作为运算符的左操作数,参数表中的操作数为运算符的右操作数。注意左、右操作数的位置理论上是不能随意互换的,比如,对于减法,操作数位置直接关系到结果的正确性。 由于函数add(x,y){x=x+y;}改变操作数的值,而在表达式x+y求值过程中改变x的值不符合日常习惯,通常的作法是在运算符重载函数中声明一个临时变量(对象)来返回运算结果。
24
例9.7矢量类加法、减法及反向运算符重载 1 #include<iostream.h> class vector{
double x,y; public: vector(double vx, double vy) {x=vx; y=vy;} vector() {x=0; y=0;} vector operator +(vector v1 ); //加法(二元)运算符重载 vector operator -(vector v1 ); //减法(二元)运算符重载 vector operator -( ); //反向(一元)运算符重载 void print( ){ cout<<x<<" "<<y<<"\n";} };
25
例9.7矢量类加法、减法及反向运算符重载 2 vector vector:: operator + (vector v1 )
v.x=x+v1.x; v.y=y+v1.y; return v; } vector vector:: operator - (vector v1 ) v.x=x-v1.x; v.y=y-v1.y; vector vector:: operator - ( ) v.x= -x; v.y= -y; void main() { vector v1(4.5,-7.8), v2(-1.5,1.2); v1.print(); v2.print(); v1=v1+v2; v2= -v1; } 运行后输出: 3 -6.6 -3 6.6
26
在C++语言中,运算符重载更多使用友元函数实现。这主要基于以下两个原因:第一,C++语言是混合型的面向对象语言,用友元提供了一种有限制地打破类的封装的机制,其目的是增加编程的灵活性和提高函数的访问效率。第二,用成员运算符重载二元运算时,两个操作数必须同为本类型操作数。如果两个操作数类型不同时,特别是左操作数不属于本类型,因而不能隐含使用this指针时,无法实现重载。友元运算符重载提供了解决这个问题的一个手段。 友元运算符重载语法形式: 声明:friend 返回值类型 operator 运算符(<参数表>);//在某类中声明的原型 定义:返回值类型 operator 运算符(<参数表>) //运算符函数头 { ……; //运算符函数体 } 3.3 友元运算符重载 说明:因为友元函数不是某个类的成员,在友元函数体中不能出现this保留字,也没有隐含的操作数。所以一元友元运算符参数表中必须显式声明一个参数,二元友元运算符参数表中必须显式声明两个参数。
27
将例9.7中的成员运算符重载改造成友元运算符重载 1
#include<iostream.h> class vector{ double x,y; public: vector(double vx, double vy) {x=vx; y=vy;} vector() {x=0; y=0;} friend vector operator +(vector v1, vector v2); //加法(二元)运算符重载 friend vector operator -(vector v1, vector v2); //减法(二元)运算符重载 friend vector operator -(vector v1); //反向(一元)运算符重载 void print( ){ cout<<x<<" "<<y<<"\n";} };
28
例9.7矢量类加法、减法及反向运算符重载 2 vector operator + (vector v1, vector v2 )
v.x=v1.x+v2.x; v.y=v1.y+v2.y; return v; } vector operator - (vector v1, vector v2 ) v.x=v1.x-v2.x; v.y=v1.y-v2.y; vector operator - (vector v1) v.x= -v1.x; v.y= -v1.y;
29
3.4 运算符重载举例 1.++运算符的重载 ++运算符有两种使用方式:前缀方式++x和后缀方式x++。作为表达式++x 返回 x 加 1 以后的值,x++ 返回 x 加 1 以前的值。++运算符重载时用不同的参数形式区分这两种形式。前缀方式用 oprerate ++( )定义,是一个普通一元成员运算符重载,后缀方式用 oprerate ++( int )定义,用的是二元成员运算符重载的形式。
30
例9.9 ++运算符重载 void main() #include<iostream.h>
例 运算符重载 #include<iostream.h> class integer { long i; public: integer(long a=0){ i=a; } integer operator ++(); integer operator ++(int); void print(){ cout<<i<<endl; } }; integer integer::operator ++() { i++; return *this; } integer integer::operator ++(int) { integer j; j.i=i++; return j; } void main() { integer x(100000),y(200000),z; z=++x; x.print(); z.print(); z=y++; y.print(); } 程序运行结果: 100001 200001 200000
31
2.下标运算符[ ]的重载 下标运算符operator[ ]被看作是一个二元运算符,必须重载为某一个类的成员函数。其一般使用格式为:
对象名[<整数表达式>] 其中对象名为左操作数,<整数表达式>为右操作数。 若obj是类class1的对象,且class1中重载了函数调用运算符operator[ ],则函数调用 obj[n]; 被解释为:obj.operator[ ] (n); 下标运算符重载用于动态构造对象数组。在对象数组的创建及访问时必须保证数组不越界。为了防止数组越界,应该事先作出预防性安排。在C++中,这是通过异常处理技术实现的。
32
例 下标运算符[ ]的重载 class String{ char *contents; int length; public:
例 下标运算符[ ]的重载 class String{ char *contents; int length; public: String(char *str) { length=strlen(str); contents=new char[length+1]; strcpy(contents,str); } char& operator [](int j) { if(j>=0 && j<length) return contents[j]; void print(String &s) { int j; for(j=0;j< length;j++) cout<<s[j]<<" "; cout<<endl; };
33
3.函数调用运算符()的重载 函数调用运算符operator ()被看作是一个二元运算符,必须重载为某一个类的成员函数。其一般使用格式为:
对象名(<参数表>) 其中对象名为左操作数,<参数表>为右操作数。 若obj是类class1的对象,且class1中重载了函数调用运算符operator (),则函数调用 obj(arg1,arg2,…); 被解释为:obj.operator () (arg1,arg2,…); 对于比较复杂的类中频繁使用的复杂算法使用重载函数调用运算符能够有效地简化程序行的书写。
34
例9.10 通过重载函数调用运算符求解一元二次方程。
#include<iostream.h> #include<math.h> class ax2bxc{ //定义一元二次方程类 double a,b,c; public: ax2bxc(){a=1;b=1;c=1;} void ax2bxc::operator ()(double A,double B,double C); // 重载函数调用运算符求解一元二次方程 }; 例9.10 通过重载函数调用运算符求解一元二次方程。 void main() { ax2bxc solution; solution (4,4,1); //重载运算符“()”的调用, ///可解释为solution.operator(4,4,1) solution (2,-3,-1); solution (1,1,1); solution (0,1,2); solution (2,3,1); } 程序运行结果: The solution of equation (4)X^2 +(4)X +(1)=0 : x1=x2=-0.5 The solution of equation (2)X^2 +(-3)X +(-1)=0 : x1= x2= The solution of equation (1)X^2 +(1)X +(1)=0 : No solutionf for this equation! Error!!! The value of (a) can not be 0! The solution of equation (2)X^2 +(3)X +(1)=0 : x1=-0.5 x2=-1 void ax2bxc::operator ()(double A,double B,double C) { a=A;b=B;c=C; if(a==0) cout<<"Error!!! The value of (a) can not be 0!"<<endl<<endl; else{ cout<<"The solution of equation (“ <<a<<")X^2 +("<<b<<")X +("<<c<<")=0 : "<<endl; if ((b*b-4*a*c)<0) cout<<" No solutionf for this equation!"<<endl; else if ((b*b-4*a*c)==0) cout<<"x1=x2="<<(-b/(2*a))<<endl; else { cout<<"x1="<<(-b+sqrt(b*b-4*a*c))/(2*a)<<endl; cout<<"x2="<<(-b-sqrt(b*b-4*a*c))/(2*a)<<endl;} }
35
4.赋值运算符重载 C++为每一个生成了一个缺省的赋值运算符。其功能是将赋值号右边的对象的数据成员逐个拷贝到赋值号右边的类对象中。缺省的赋值运算符采用的这种复制对象的方法称为浅复制,在对象成员含有指针或数组的情况下,浅复制会出问题。此时就应该为类编写用户定义的赋值运算符重载函数,实现正确的(深)复制。
36
缺省赋值运算与对象浅复制可能发生的问题 #include<string.h>
#include<iostream.h> class str{ char *pc; public: str(const char* s) { int n=strlen(s); pc=new char[n+1]; strcpy(pc,s); } void print(){cout<<pc<<endl;} }; void main() { str a1("first"); str a2("second"); a3.print(); a1=a2; a1.print(); 在这个例子中,语句a1=a2;调用缺省赋值运算操作,将对象a2的数据成员逐一复制给a1的各数据成员。当a2的字符串指针变量pc的值赋给a1的指针pc之后,a1的pc将与a2的pc指向同一个字符串,致使a1原来指向的字符串变成一块无法访问和释放的内存垃圾。同时,在释放对象a1和a2时,a2原来指向的字符串将被释放两次。这些问题都需要通过用户定义赋值运算符重载的深复制策略来解决。
37
用户定义的深复制策略赋值运算符重载 1 #include<string.h>
#include<iostream.h> class str{ char *pc; public: str(const char* s) { int n=strlen(s); pc=new char[n+1]; strcpy(pc,s); cout<<”Constractor called!”<<endl; } void str::operator = ( const str& a); //赋值运算符重载定义。 void print(){cout<<pc<<endl;} ~str(){cout<<"Destrctor called!"<<endl;} };
38
用户定义的深复制策略赋值运算符重载 2 void str::operator = ( const str& a) {
说明:(1)深复制方法是将原来的指针释放后重新分配,然后再进行数据复制。避免了内存垃圾和同一内存块重复释放的问题。 (2)赋值运算目的就是改变左操作数的值,因此函数体中不需要引入临时对象。 注意:对象初始化时的赋值和已创建对象之间的赋值虽然都涉及对象的复制,但它们是两个不同的操作。对象初始化首先是为新对象分配存储空间,然后执行对象复制。 如:Point p1, p2(3.14, 4.06); Point p3=p2; //调用拷贝构造初始化函数 p1=p2; //调用赋值运算符重载 所以,对于应该采用深复制的对象,用户应该同时为它的类定义拷贝初始化构造函数。 void str::operator = ( const str& a) { if (this==&a) return; delete pc; //释放原来的字符串 int n=strlen(a.pc); pc=new char[n]; //按新长度为字符串分配内存 strcpy( pc, a.pc); //字符串拷贝 } void main() str a1("first"); str a2("second"); a1.print(); a1=a2; 程序输出: Constrct called! first second Destrctor called!
39
5.复数类中的运算符重载 例9.11一个完整复数类定义及测试程序 1 #include<iostream.h>
class Complex { double real, image; public: Complex(double r=0, double i=0); Complex(const Complex& other); void print(); Complex operator + ( const Complex& other); Complex operator - ( const Complex& other); //减法, 二元 Complex operator - ( ); //求负,一元 Complex operator = ( const Complex& other); //赋值, 二元 };
40
例9.11一个完整复数类定义及测试程序 2 Complex::Complex(double r, double i) { real=r;
image=i; } Complex::Complex(const Complex& other) { //此拷贝构造函数与缺省拷贝函数相同,可以省略。 real=other.real; image=other.image; void Complex::print() { cout<<real; if (image>0) cout<<"+"<<image<<"i"; else if (image<0) cout<<image<<"i"; cout<<"\n"; Complex Complex:: operator + (const Complex& other) { Complex temp; temp.real=real+other.real; //相当于temp.real=this->real+other.real; temp.image= image +other.image; return temp;
41
例9.11一个完整复数类定义及测试程序 3 Complex Complex:: operator - (const Complex& other) { Complex temp; temp.real=real-other.real; temp.image= image -other.image; return temp; } Complex Complex:: operator - ( ) temp.real= - real; temp.image= - image; Complex Complex:: operator = (const Complex& other) { //此赋值运算符的重载与缺省赋值运算相同,可以省略。 real= other.real; image= other.image; return *this; void main() { Complex c1(1,2); Complex c2(2); Complex c3(c1); c3.print(); c1=c1+c2+c3; c2= - c3; c3=c2-c1; } 程序输出: 1+2i -5-6i
Similar presentations