第 5 章(4)━━运算符重载

上传人:re****.1 文档编号:567399098 上传时间:2024-07-20 格式:PPT 页数:44 大小:290KB
返回 下载 相关 举报
第 5 章(4)━━运算符重载_第1页
第1页 / 共44页
第 5 章(4)━━运算符重载_第2页
第2页 / 共44页
第 5 章(4)━━运算符重载_第3页
第3页 / 共44页
第 5 章(4)━━运算符重载_第4页
第4页 / 共44页
第 5 章(4)━━运算符重载_第5页
第5页 / 共44页
点击查看更多>>
资源描述

《第 5 章(4)━━运算符重载》由会员分享,可在线阅读,更多相关《第 5 章(4)━━运算符重载(44页珍藏版)》请在金锄头文库上搜索。

1、C+程序设计程序设计第第5章章(4) 运算符重载运算符重载1主要内容主要内容l运算符重载的作用运算符重载的作用l运算符重载函数运算符重载函数l运算符重载的实现运算符重载的实现l重载为成员函数重载为成员函数双目运算符重载双目运算符重载l重载为成员函数重载为成员函数单目运算符重载单目运算符重载l重载为成员函数重载为成员函数 “+”和和“-”运算符重载运算符重载l重载为友元函数重载为友元函数双目运算符重载双目运算符重载l重载为友元函数重载为友元函数单目运算符重载单目运算符重载l运算符重载的规则运算符重载的规则l插入运算符插入运算符“” 的重载的重载 只能重载为友元函数只能重载为友元函数l类型转换函数

2、类型转换函数l自定义字符串类自定义字符串类lC+标准库中的标准库中的string类类2运算符重载的作用运算符重载的作用l所谓重载,就是重新赋予新的含义。所谓重载,就是重新赋予新的含义。l运算符重载的必要性:运算符重载的必要性: 对于每一种基本数据类型,对于每一种基本数据类型,C+中都作了预定义,定义了该类型数据的编码方式和存中都作了预定义,定义了该类型数据的编码方式和存储方式,以及对它所能进行的各种运算,即预定义了运算符!使用时必须遵循它的储方式,以及对它所能进行的各种运算,即预定义了运算符!使用时必须遵循它的规定。规定。 【例】【例】 整型数:整型数:算术运算:算术运算: + - * / %

3、 位运算:位运算: & | 关系运算关系运算 、逻辑运算、逻辑运算 、赋值运算、赋值运算 、 实型数:实型数:算术运算:算术运算: + - * / 关系运算关系运算 、逻辑运算、逻辑运算 、赋值运算、赋值运算 、 在面向对象程序设计中,增加了用户自定义的数据类型,即用户自定义的类,在这类在面向对象程序设计中,增加了用户自定义的数据类型,即用户自定义的类,在这类数据类型上也需要进行相关运算,必须对相关运算符进行重新的定义。数据类型上也需要进行相关运算,必须对相关运算符进行重新的定义。 【例】【例】 复数类:复数类:算术运算:算术运算: + - * / 赋值运算:赋值运算: = += -= 3运算

4、符重载函数运算符重载函数lC+中的重载有:中的重载有: 函数重载:函数重载:使用一个已有的函数名(即已使用该函数名定义过函数)来重新定义一个使用一个已有的函数名(即已使用该函数名定义过函数)来重新定义一个新的函数,使之实现新的功能。这样同一个函数名就可以代表不同的函数。新的函数,使之实现新的功能。这样同一个函数名就可以代表不同的函数。 运算符重载:运算符重载:对于对于C+中预定义的运算符也可以像函数一样重载,即定义一个运算符中预定义的运算符也可以像函数一样重载,即定义一个运算符重载函数!运算符重载本质上就是函数重载。重载函数!运算符重载本质上就是函数重载。l运算符重载函数:运算符重载函数: 对

5、于对于C+预定义的某个运算符,在该运算符重载函数中重新定义其功能,使之能够作预定义的某个运算符,在该运算符重载函数中重新定义其功能,使之能够作用于某类对象的运算。用于某类对象的运算。 基于某个类,可对其相关的若干个运算符进行重载,分别定义各运算符重载函数,以基于某个类,可对其相关的若干个运算符进行重载,分别定义各运算符重载函数,以完成该类对象的各种运算。完成该类对象的各种运算。lC+中的多态性有:中的多态性有: 编译时的多态性:编译时的多态性:通过通过“函数重载函数重载”、“运算符重载运算符重载”来实现。来实现。 运行时的多态性:运行时的多态性:通过通过“继承机制继承机制+虚函数虚函数”来实现

6、。来实现。4运算符重载的实现运算符重载的实现l关于运算符重载:关于运算符重载: 只能重载只能重载C+中预定义的运算符,不能自己臆造运算符。中预定义的运算符,不能自己臆造运算符。 重新赋予运算符新的功能是通过函数实现的,即定义运算符重载函数重新赋予运算符新的功能是通过函数实现的,即定义运算符重载函数 。 用户根据需要对运算符赋予一种或多种新的功能,以配合用户自定义的类,因此运算用户根据需要对运算符赋予一种或多种新的功能,以配合用户自定义的类,因此运算符重载必须作用于类的对象,至少要有一个操作数是类的对象。符重载必须作用于类的对象,至少要有一个操作数是类的对象。 运算符重载后,对于同一个运算符,将

7、根据不同的运算对象完成不同的操作,体现了运算符重载后,对于同一个运算符,将根据不同的运算对象完成不同的操作,体现了面向对象程序设计技术的多态性。面向对象程序设计技术的多态性。l运算符重载的两种运算符重载的两种实现方法:实现方法: 重载为类的成员函数。重载为类的成员函数。 重载为类的友元函数。重载为类的友元函数。l实现机制:实现机制: 将指定的运算表达式转化为对运算符将指定的运算表达式转化为对运算符重载重载函数的调用,运算对象转化为运算符函数的调用,运算对象转化为运算符重载重载函函数的实参。数的实参。 编译系统对运算符重载函数的选择,遵循函数重载的选择规则。编译系统对运算符重载函数的选择,遵循函

8、数重载的选择规则。5重载为成员函数重载为成员函数双目运算符重载双目运算符重载l双目运算符重载函数的定义:双目运算符重载函数的定义: class 类名类名 返回值类型返回值类型 operator 运算符运算符 ( 形参形参 ); ; l也可在类外作定义性声明:也可在类外作定义性声明: 返回值类型返回值类型 类名类名 : operator 运算符运算符 ( 形参形参 ) 函数体函数体 l双目运算符重载为成员函数:双目运算符重载为成员函数: 只有一个形参,为双目运算符的右操作数。只有一个形参,为双目运算符的右操作数。 程序中若出现表达式:程序中若出现表达式: c1 运算符运算符 c2 则编译器将其解

9、释为:则编译器将其解释为: c1. operator 运算符运算符 ( c2 ) 切记:左操作数切记:左操作数c1必须是该类对象,右操作数必须是该类对象,右操作数c2可以是类型与形参兼容的数据。可以是类型与形参兼容的数据。一起构成了运算符重载函数的函数名一起构成了运算符重载函数的函数名声明在类中,作为该类的成员函数声明在类中,作为该类的成员函数6【例】【例】(复数类、双目运算符重载为成员函数)(复数类、双目运算符重载为成员函数)# includeclass Complex double real , image ; public: Complex( double r =0 , double i

10、 =0 ) : real ( r ) , image ( i ) void show( ) cout “复数:复数:( ” real “ , ” image “i )n” ; Complex & operator = ( Complex & ) ; void operator += ( Complex & ) ; Complex operator + ( Complex & ) ; Complex operator + ( double ) ; Complex operator - ( Complex & ) ; Complex operator * ( Complex & ) ; Compl

11、ex operator / ( Complex & ) ;Complex & Complex: operator = ( Complex &c ) real = c.real ; image = c.image ; return *this ; 注意:注意: 运算符运算符“=”是用于同类两个是用于同类两个对象之间的相互赋值,若类中对象之间的相互赋值,若类中没有给出运算符没有给出运算符“=” 重载函数,重载函数,C+ 编译器为每个类生成一个编译器为每个类生成一个默认的默认的 operator = 重载函数,重载函数,其语义为按类成员数据逐个相其语义为按类成员数据逐个相互赋值。互赋值。 虽然这种默

12、认的赋值重载函虽然这种默认的赋值重载函数对复数是合适的,但对某些数对复数是合适的,但对某些类这种默认的赋值重载可能产类这种默认的赋值重载可能产生问题,那时就需要自定义赋生问题,那时就需要自定义赋值重载函数。值重载函数。7void Complex: operator += ( Complex &c ) real += c.real ; image += c.image ; Complex Complex: operator + ( Complex &c ) Complex temp ( real + c.real , image + c.image ) ; /创建局部对象创建局部对象temp r

13、eturn temp ; Complex Complex: operator + ( double r ) return Complex ( real + r , image ) ; /创建无名临时对象创建无名临时对象Complex Complex: operator - ( Complex &c ) return Complex ( real - c.real , image - c.image ) ; /创建无名临时对象创建无名临时对象Complex Complex: operator * ( Complex &c ) Complex temp ; /创建局部对象创建局部对象temp te

14、mp.real = real*c. real - image*c. image ; temp.image = real*c.image + image*c.real ; return temp ; 8Complex Complex: operator / ( Complex &c ) double d = c.real*c.real + c.image* c.image ; Complex temp ; /创建局部对象创建局部对象temp temp.real = ( real * c.real + image * c.image ) / d ; temp.image = ( image * c

15、.real - real * c.image ) / d ; return temp ; void main ( ) Complex c1( 1 , 2 ) , c2( 3 , 4 ) , c3( 5 , 6 ) , c4 , c5 , c6 ; c1.show( ) ; c2.show( ) ; c3.show( ) ; c4 = c1 + c2 ; /解释为:解释为:c4.operator= ( c1.operator+ ( c2 ) ) c4.show( ) ; c5 = c3 - c2 + c1 ; /解释为:解释为:c5.operator= ( (c3.operator- ( c2

16、).operator+ (c1) ) c5.show( ) ; c6 = c3 + 0.5 ; /解释为:解释为:c6.operator= ( c3.operator+(0.5) ) c6.show( ) ; ( c1* c2 ) . show( ) ; /解释为:解释为:c1.operator * (c2) ( c2 / c1 ) . show( ) ; /解释为:解释为:c2.operator / (c1) c1 += c2 ; /解释为:解释为:c1.operator+= ( c2 ) c1.show( ) ; 运行:运行:复数:复数:(1 , 2i )复数:复数:(3 , 4i )复数

17、:复数:(5 , 6i )复数:复数:(4 , 6i )复数:复数:(3 , 4i )复数:复数:(5.5 , 6i )复数:复数:(-5 , 10i )复数:复数:(2.2 , -0.4i )复数:复数:(4 , 6i )9重载为成员函数重载为成员函数单目运算符重载单目运算符重载l单目运算符重载函数的定义:单目运算符重载函数的定义: class 类名类名 返回值类型返回值类型 operator 运算符运算符 ( ); ;l单目运算符重载为成员函数:单目运算符重载为成员函数: 程序中若出现表达式:程序中若出现表达式: 运算符运算符 c1 则编译器将其解释为:则编译器将其解释为: c1. ope

18、rator 运算符运算符 ( ) 其中:其中:c1必须是该类的对象。必须是该类的对象。 对于自增对于自增“+”和自减和自减“-”运算符,存在前置和后置情况,为使运算符,存在前置和后置情况,为使C+编译器能区分编译器能区分前置和后置情况,定义这两个运算符重载函数时,必须有所区别。前置和后置情况,定义这两个运算符重载函数时,必须有所区别。 单目运算符因只有一个操作数,单目运算符因只有一个操作数,故重载为成员函数时没有形参。故重载为成员函数时没有形参。10重载为成员函数重载为成员函数 “+”和和“-”运算符重载运算符重载l自增自增“+”和自减和自减“-”运算符重载函数的定义:运算符重载函数的定义:

19、class 类名类名 返回值类型返回值类型 operator + ( ) ; /前置前置“+” 返回值类型返回值类型 operator + ( int ) ; /后置后置“+” 返回值类型返回值类型 operator - ( ) ; /前置前置“-” 返回值类型返回值类型 operator - ( int ) ; /后置后置“-” ;l说明:说明: 对于对于+和和-运算符,存在前置和后置情况,为使运算符,存在前置和后置情况,为使C+编译器能区分前置和后置情况,编译器能区分前置和后置情况,定义后置运算符重载函数增加一个形参定义后置运算符重载函数增加一个形参int,其本身没有实际意义,只作为区分后

20、置其本身没有实际意义,只作为区分后置运算符的标识。运算符的标识。11重载为成员函数重载为成员函数 “+”和和“-”运算符重载运算符重载l+和和-运算符重载为成员函数:运算符重载为成员函数: 程序中若出现表达式:程序中若出现表达式: +c1 则编译器将其解释为:则编译器将其解释为: c1.operator+ ( ) 其中:其中:c1必须是该类的对象。必须是该类的对象。 程序中若出现表达式:程序中若出现表达式: c1+ 则编译器将其解释为:则编译器将其解释为: c1.operator+ ( int ) 其中:其中:c1必须是该类的对象。必须是该类的对象。 程序中若出现表达式:程序中若出现表达式:

21、-c1 则编译器将其解释为:则编译器将其解释为: c1.operator- ( ) 其中:其中:c1必须是该类的对象。必须是该类的对象。 程序中若出现表达式:程序中若出现表达式: c1- 则编译器将其解释为:则编译器将其解释为: c1.operator- ( int ) 其中:其中:c1必须是该类的对象。必须是该类的对象。12【例】【例】(日期类、(日期类、+、- 运算符重载为成员函数)运算符重载为成员函数)# includeclass Date int year , month , day ; static int md 12 ; /静态成员数据静态成员数据 public: Date ( i

22、nt y=1900 , int m=1 , int d=1 ) : year ( y ) , month ( m ) , day ( d ) if ( ( year%4=0 & year%100!=0 ) | ( year%400=0 ) ) md 1 =29 ; else md 1 =28 ; void set ( int y , int m , int d ) year = y ; month = m ; day = d ; if ( ( year%4=0 & year%100!=0 ) | ( year%400=0 ) ) md 1 =29 ; else md 1 =28 ; void

23、show ( ) cout year “t年年” month “月月” day 31 ) +year ; month=1 ; day=1 ; if ( month !=12 & day md month-1 ) +month ; day=1 ; return *this ; Date Date: operator + ( int ) /后置后置+ Date d = *this ; day+ ; if ( month =12 & day 31 ) +year ; month=1 ; day=1 ; if ( month !=12 & day md month-1 ) +month ; day=1

24、 ; return d ; Date Date: operator - ( ) /前置前置- day- ; if ( month =1 & day 1 ) - year ; month=12 ; day=31 ; if ( month !=1 & day 1 ) - month ; day = md month-1 ; return *this ; Date Date: operator - ( int ) /后置后置- Date d = *this ; day- ; if ( month =1 & day 1 ) - year ; month=12 ; day=31 ; if ( month

25、 !=1 & day 1 ) - month ; day = md month-1 ; return d ; 14void main ( ) int y , dd 12 = 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ; cout y ; if ( ( y%4=0 & y%100!=0 ) | ( y%400=0 ) ) dd 1 = 29 ; else dd 1 =28 ; Date d ; for ( int i=1 ; i=12 ; i+ ) d.set ( y, i, dd i-1 ) ; d.show( ) ;

26、cout “1天后:天后:” ; (+d) . show( ) ; /改为改为(d+).show( ); 结果又如何?结果又如何? cout endl ; for ( i=1 ; i=12 ; i+ ) d.set ( y, i, 1 ) ; d.show( ) ; cout “1天前:天前:” ; (-d).show( ) ; /改为改为(d-).show( ); 结果又如何?结果又如何? cout endl ; 运行:运行:请输入年份:请输入年份:2000 2000年年1月月31日日 1天后:天后: 2000年年2月月1日日2000年年2月月29日日 1天后:天后: 2000年年3月月1日

27、日2000年年3月月31日日 1天后:天后: 2000年年4月月1日日2000年年4月月30日日 1天后:天后: 2000年年5月月1日日2000年年5月月31日日 1天后:天后: 2000年年6月月1日日2000年年6月月30日日 1天后:天后: 2000年年7月月1日日2000年年7月月31日日 1天后:天后: 2000年年8月月1日日2000年年8月月31日日 1天后:天后: 2000年年9月月1日日2000年年9月月30日日 1天后:天后: 2000年年10月月1日日2000年年10月月31日日 1天后:天后: 2000年年11月月1日日2000年年11月月30日日 1天后:天后: 2

28、000年年12月月1日日2000年年12月月31日日 1天后:天后: 2001年年1月月1日日2000年年1月月1日日 1天前:天前:1999年年12月月31日日2000年年2月月1日日 1天前:天前: 2000年年1月月31日日2000年年3月月1日日 1天前:天前: 2000年年2月月29日日2000年年4月月1日日 1天前:天前: 2000年年3月月31日日2000年年5月月1日日 1天前:天前: 2000年年4月月30日日2000年年6月月1日日 1天前:天前: 2000年年5月月31日日2000年年7月月1日日 1天前:天前: 2000年年6月月30日日2000年年8月月1日日 1天

29、前:天前: 2000年年7月月31日日2000年年9月月1日日 1天前:天前: 2000年年8月月31日日2000年年10月月1日日 1天前:天前: 2000年年9月月30日日2000年年11月月1日日 1天前:天前: 2000年年10月月31日日2000年年12月月1日日 1天前:天前: 2000年年11月月30日日15重载为友元函数重载为友元函数双目运算符重载双目运算符重载l双目运算符重载函数的定义:双目运算符重载函数的定义: class 类名类名 friend 返回值类型返回值类型 operator 运算符运算符 ( 形参形参1 ,形参形参2 ) ; ;l一般在类外对友元函数作定义性声明

30、:一般在类外对友元函数作定义性声明: 返回值类型返回值类型 operator 运算符运算符 ( 形参形参1 ,形参形参2 ) 函数体函数体 l双目运算符重载为友元函数:双目运算符重载为友元函数: 形参有形参有2个,其中:个,其中:“形参形参1”是运算符的左操作数,是运算符的左操作数,“形参形参2”是运算符的右操作数。是运算符的右操作数。 程序中若出现表达式:程序中若出现表达式: c1 运算符运算符 c2 则编译器将其解释为:则编译器将其解释为:operator 运算符运算符 ( c1 , c2 ) 切记:切记: 若若c1不是、而不是、而c2是某类的对象,则该函数必须是该类的友元函数。是某类的对

31、象,则该函数必须是该类的友元函数。友元函数不是成员函数,不要加友元函数不是成员函数,不要加“类名类名:”声明在类中,作为该类的成员函数声明在类中,作为该类的成员函数16【例】【例】(复数类、双目运算符重载为友元函数)(复数类、双目运算符重载为友元函数) # include class Complex double real , image ; public: Complex( double r =0 , double i =0 ) : real ( r ) , image ( i ) void show( ) cout “复数:复数:( ” real “ , ” image “i )n” ;

32、friend void operator -= ( Complex & , const Complex & ) ; friend Complex operator - ( const Complex & , const Complex & ) ; friend Complex operator - ( const Complex & , double ) ; friend Complex operator - ( double , const Complex & ) ; friend bool operator = ( const Complex & , const Complex & ) ;

33、 friend bool operator != ( const Complex & , const Complex & ) ;注意:注意:在函数形参表中,一般将其值无需修改的形参对象定义在函数形参表中,一般将其值无需修改的形参对象定义为为 const。目的是:若在函数中发生误操作,出现修改目的是:若在函数中发生误操作,出现修改该形参对象数据时,编译系统将给出错误信息。该形参对象数据时,编译系统将给出错误信息。 注意:注意:在函数形参表中,使用引用类型的对象作为在函数形参表中,使用引用类型的对象作为函数的形参,可以提高函数的运行效率。函数的形参,可以提高函数的运行效率。17void opera

34、tor -= ( Complex &c1 , const Complex &c2 ) c1.real -= c2.real ; c1.image -= c2.image ; Complex operator - ( const Complex &c1 , const Complex &c2 ) Complex temp ( c1.real - c2.real , c1.image - c2.image ) ; return temp ; Complex operator - ( const Complex &c , double r ) return Complex ( c.real - r

35、, c.image ) ; Complex operator - ( double r , const Complex &c ) return Complex ( r - c.real , -c.image ) ; bool operator = ( const Complex &c1 , const Complex &c2 ) if ( c1.real=c2.real & c1.image=c2. image ) return true ; else return false ; bool operator != ( const Complex &c1 , const Complex &c2

36、 ) if ( c1.real!=c2.real | c1.image!=c2. image ) return true ; else return false ; 18void main ( ) Complex c1( 1 , 2 ) , c2( 3 , 4 ) , c3( 5 , 6 ) , c4 , c5 , c6 ; c1.show( ) ; c2.show( ) ; c3.show( ) ; c4 = c1 - c2 ; /解释为:解释为: c4.operator= ( operator-( c1 , c2 ) ) c4.show( ) ; c5 = c3 - c2 - 2 ; /解

37、释为:解释为:c5.operator=( operator- ( operator-(c3 , c2) , 2 ) ) c5.show( ) ; c6 = 2 - c1 ; /解释为:解释为:c6.operator=( operator-( 2 , c1) ) c6.show( ) ; if ( c1 = c2 ) /解释为:解释为:operator = ( c1 , c2 ) cout “c1等于等于c2 ! n” ; else cout “c1不等于不等于c2 ! n” ; if ( c1 != c3 ) /解释为:解释为:operator != ( c1 , c3 ) cout “c1不

38、等于不等于c3 ! n” ; else cout “c1等于等于c3 ! n” ; c2 -= c1 ; /解释为:解释为:operator -= ( c2 , c1 ) c2.show( ) ; 运行:运行:复数:复数:(1 , 2i )复数:复数:(3 , 4i )复数:复数:(5 , 6i )复数:复数:(-2 , -2i )复数:复数:(0 , 2i )复数:复数:(1 , -2i )c1不等于不等于c2 !c1不等于不等于c3 !复数:复数:(2 , 2i )19重载为友元函数重载为友元函数单目运算符重载单目运算符重载l单目运算符重载函数的定义:单目运算符重载函数的定义: class

39、 类名类名 friend 返回值类型返回值类型 operator 运算符运算符 ( 形参形参 ); ;l单目运算符重载为友元函数:单目运算符重载为友元函数: 程序中若出现表达式:程序中若出现表达式: 运算符运算符 c1 则编译器将其解释为:则编译器将其解释为: operator 运算符运算符 ( c1 ) 对对于于自自增增“+”和和自自减减“-”运运算算符符,存存在在前前置置和和后后置置情情况况,为为了了使使C+编编译译器器能能区区分前置和后置情况,定义这两个运算符重载函数时,必须有所区别。分前置和后置情况,定义这两个运算符重载函数时,必须有所区别。 单目运算符只有一个操作数,故单目运算符只有

40、一个操作数,故重载为友元函数时对应一个形参。重载为友元函数时对应一个形参。20重载为友元函数重载为友元函数 “+”和和“-”运算符重载运算符重载l自增自增“+”和自减和自减“-”运算符重载函数的定义:运算符重载函数的定义: class 类名类名 friend 返回值类型返回值类型 operator + ( 形参形参 ); /前置前置“+” friend 返回值类型返回值类型 operator + (形参形参 ,int ); /后置后置“+” friend 返回值类型返回值类型 operator - (形参形参 ); /前置前置“-” friend 返回值类型返回值类型 operator - (

41、 形参,形参, int ); /后置后置“-” ;l+和和-运算符重载为友元函数:运算符重载为友元函数: 程序中若出现表达式:程序中若出现表达式: +c1 则编译器将其解释为:则编译器将其解释为: operator+ ( c1 ) 程序中若出现表达式:程序中若出现表达式: c1+ 则编译器将其解释为:则编译器将其解释为: operator+ ( c1 , int )21【例】【例】(计数器类、(计数器类、“+”和和“-”重载为友元函数)重载为友元函数)# includeclass Counter int n ; public: Counter ( int x=0 ) n = x ; void

42、show( ) cout “计数值计数值=t” n 只能重载为成员函数,不能重载为友元函数!只能重载为成员函数,不能重载为友元函数! 赋值运算符赋值运算符“=”,其重载函数一般可省略不写,编译器为每个类自动生成一个默认,其重载函数一般可省略不写,编译器为每个类自动生成一个默认的的“operator =”重载函数,其语义为按类成员数据依次相互赋值。注意,若某类对重载函数,其语义为按类成员数据依次相互赋值。注意,若某类对象的成员数据中有指向动态分配的数据时,对象之间就不能直接相互赋值,否则在象的成员数据中有指向动态分配的数据时,对象之间就不能直接相互赋值,否则在程序执行中会出现运行错误,此时不能使

43、用系统给出的默认赋值重载函数,必须在程序执行中会出现运行错误,此时不能使用系统给出的默认赋值重载函数,必须在类中自定义赋值重载函数,且只能重载为成员函数!(后续章节介绍)类中自定义赋值重载函数,且只能重载为成员函数!(后续章节介绍) 运算符运算符流插入流插入 只能重载为友元函数!只能重载为友元函数!23插入运算符插入运算符“” 的重载的重载 只能重载为友元函数只能重载为友元函数l关于表达式关于表达式 cout 基本类型数据基本类型数据 、 cout 字符串字符串 : 插入运算符插入运算符“” 在在C+中是预定义为位左移运算符,由于在中是预定义为位左移运算符,由于在C+类库的类库的 输出流类输出

44、流类 ostream 中对其进行了重载,使之能用作中对其进行了重载,使之能用作基本类型数据、字符串基本类型数据、字符串的输出运算符。的输出运算符。 在头文件在头文件 iostream.h / iostream 中定义了四个全局流对象(中定义了四个全局流对象( cin、cout、cerr、clog),),其中其中 cout、cerr、clog 都是都是 输出流类输出流类 ostream 的对象。的对象。 在在 输出流类输出流类 ostream 中,对往输出流中插入中,对往输出流中插入“” 基本类型数据、字符串基本类型数据、字符串分别进行分别进行重载。在重载。在 VC+6.0 中重载了中重载了19

45、种不同形式的成员函数,重载种不同形式的成员函数,重载“”函数原型为:函数原型为: ostream & operator ( int ); ostream & operator ( double ); ostream & operator ( char * ); 【例】例】cout 3+5 “123” 5.5 ; 分析表达式的执行过程。分析表达式的执行过程。 返回值为返回值为ostream类的对象引用,实际上就是返回当前输出流!类的对象引用,实际上就是返回当前输出流!24插入运算符插入运算符“” 的重载的重载 只能重载为友元函数只能重载为友元函数 输出流类输出流类 ostream 的声明在头文件

46、的声明在头文件 iostream.h / iostream 中,若要对中,若要对基本类型数基本类型数据、字符串据、字符串进行输出操作,程序中必须包含该头文件。进行输出操作,程序中必须包含该头文件。 注意:在表达式注意:在表达式 cout 基本类型数据基本类型数据 、 cout 字符串字符串 中,左操作数是中,左操作数是输出流输出流类类 ostream 的对象的对象 cout,右操作数才是右操作数才是基本类型数据、字符串基本类型数据、字符串。 对于用户自定义类型的数据(即类的对象),不能直接用插入运算符对于用户自定义类型的数据(即类的对象),不能直接用插入运算符“” 进行输进行输出,即不支持表达

47、式出,即不支持表达式 cout 某类对象某类对象 ,必须在该类中对插入运算符,必须在该类中对插入运算符“” 重载,重载,由于左操作数为由于左操作数为cout,非本类对象,因此只能重载为友元函数!非本类对象,因此只能重载为友元函数! 在用户自定义的类中声明重载运算符在用户自定义的类中声明重载运算符“” 为友元函数:为友元函数: friend ostream & operator ” 的重载的重载 只能重载为友元函数只能重载为友元函数l关于表达式关于表达式 cin 基本类型变量名基本类型变量名 、cin 字符数组名字符数组名 : 提取运算符提取运算符“” 在在C+中是预定义为位右移运算符,由于在中

48、是预定义为位右移运算符,由于在C+类库的类库的 输入流类输入流类 istream 中对其进行了重载,使之能用作中对其进行了重载,使之能用作基本类型数据、字符串基本类型数据、字符串的输入运算符。的输入运算符。 在头文件在头文件 iostream.h / iostream 中定义了四个全局流对象(中定义了四个全局流对象( cin、cout、cerr、clog),),其中其中 cin 是是 输入流类输入流类 istream 的对象。的对象。 在在 输入流类输入流类 istream 中,对从输入流中提取中,对从输入流中提取“” 基本类型数据、字符串基本类型数据、字符串分别进行分别进行重载。在重载。在

49、VC+6.0 中重载了中重载了18种不同形式的成员函数,重载种不同形式的成员函数,重载“”函数原型为:函数原型为: istream & operator ( int ) istream & operator ( double ) istream & operator ( char * ) 【例】例】int a ; double b ; char c ; cin a b c ; 分析表达式的执行过程。分析表达式的执行过程。 返回值为返回值为istream类的对象引用,实际上就是返回当前输入流!类的对象引用,实际上就是返回当前输入流!26提取运算符提取运算符“” 的重载的重载 只能重载为友元函数只

50、能重载为友元函数 输入流类输入流类 istream 的声明在头文件的声明在头文件 iostream.h / iostream 中,若要对中,若要对基本类型数据、基本类型数据、字符串字符串进行输入操作,程序中必须包含该头文件。进行输入操作,程序中必须包含该头文件。 注意:在表达式注意:在表达式 cin 基本类型变量名基本类型变量名 、 cin 字符数组名字符数组名 中,左操作数是中,左操作数是输入输入流类流类 istream 的对象的对象 cin,右操作数才是右操作数才是基本类型变量名基本类型变量名 、字符数组名、字符数组名 。 对于用户自定义类型的变量(即类的对象),不能直接用提取运算符对于用

51、户自定义类型的变量(即类的对象),不能直接用提取运算符“” 进行输进行输入,即不支持表达式入,即不支持表达式 cin 某类对象名某类对象名 ,必须在该类中对提取运算符,必须在该类中对提取运算符“”重载,重载,由于左操作数为由于左操作数为cin,非本类对象,因此只能重载为友元函数!非本类对象,因此只能重载为友元函数! 在用户自定义的类中声明提取运算符在用户自定义的类中声明提取运算符“” 为友元函数:为友元函数: friend istream & operator ( istream & ,自定义类自定义类 & )27【例】【例】(定义学生类,使之能用插入运算符(定义学生类,使之能用插入运算符“”

52、来整体输入一个学生的资料。)来整体输入一个学生的资料。)#include#includeclass Student int id ; char name 10 ; int score ; public: Student ( int i=0 , char *na=0 , int s=0 ) id=i ; if ( na ) strcpy( name , na ) ; score=s ; friend bool operator ( istream & , Student & ) ; friend ostream & operator ( ostream & , Student & ) ; ;bo

53、ol operator ( Student &s1 , Student &s2 ) if ( s1.score ( istream & in , Student &s ) cout s.id s.name s.score ; return in ; ostream & operator ( ostream & out , Student &s ) out “学号学号:” s.id “t姓名姓名:” s.name “t成绩成绩:” s.score endl ; return out ; void main ( ) Student s 4 , t ; int i , j ; for ( i=0 ;

54、 i s i ; cout“排序前:排序前:n” ; for ( i=0 ; i4 ; i+ ) cout s i ; for ( i=0 ; i3 ; i+ ) for ( j=i+1 ; j4 ; j+ ) if ( s i s j ) t = s i ; s i = s j ; s j = t ; cout“排序后:排序后:n” ; for ( i=0 ; i4 ; i+ ) cout s i ; 运行:运行:请输入学号、姓名、成绩:请输入学号、姓名、成绩:111 aaa 88 请输入学号、姓名、成绩:请输入学号、姓名、成绩:222 bbb 99 请输入学号、姓名、成绩:请输入学号、姓名

55、、成绩:333 ccc 77 请输入学号、姓名、成绩:请输入学号、姓名、成绩:444 ddd 98 排序前:排序前:学号:学号:111 姓名:姓名:aaa 成绩:成绩:88学号:学号:222 姓名:姓名:bbb 成绩:成绩:99学号:学号:333 姓名:姓名:ccc 成绩:成绩:77学号:学号:444 姓名:姓名:ddd 成绩:成绩:98排序后:排序后:学号:学号:222 姓名:姓名:bbb 成绩:成绩:99学号:学号:444 姓名:姓名:ddd 成绩:成绩:98学号:学号:111 姓名:姓名:aaa 成绩:成绩:88学号:学号:333 姓名:姓名:ccc 成绩:成绩:7729类型转换函数类型

56、转换函数l类类型型转转换换函函数数的的作作用用:类类型型转转换换函函数数是是类类的的成成员员函函数数,其其功功能能是是将将该该类类的的对对象象数数据据,转转换换成成另另一一类类型型的的数数据据。所所谓谓 “另另一一类类型型” 可可以以是是基基本本数数据据类类型型,也也可可以以是是已已定定义义的构造数据类型。的构造数据类型。l类型转换函数的定义:类型转换函数的定义: class 类名类名 operator 另一类型名另一类型名 ( ); ; 一起构成了类型转换函数的函数名,一起构成了类型转换函数的函数名,其中另一类型指转换后的数据类型。其中另一类型指转换后的数据类型。没有形参,也不能指定返回值类

57、型,其返回值类没有形参,也不能指定返回值类型,其返回值类型由型由operator后面的后面的 “另一类型另一类型” 确定。确定。30【例】【例】(类型转换函数)(类型转换函数)#includeclass Money int yuan , jiao , fen ; public:Money ( int y=0 , int j=0 , int f=0 ) yuan=y ; jiao=j ; fen=f ; void show( ) cout yuan “元元” jiao “角角” fen “分分t” ; operator float ( ) return ( yuan + jiao/10. + f

58、en/100. ) ; operator int ( ) return ( yuan*100 + jiao*10 + fen ) ; ;void main() Money m1( 1 , 22 , 33 ) , m2( 2 , 44 , 66 ) ; m1.show( ) ; cout “=t” float ( m1) “(元元)n” ; m2.show() ; cout “=t” ( int ) m2 ( mystring & ) ; bool operator = ( mystring & ) ; char & operator ( int ) ; 友元重载运算符:友元重载运算符:istr

59、eam & operator ( istream & , mystring & ) ; ostream & operator ( ostream & , mystring & ) ; 33【例】【例】(自定义一个简单的字符串类(自定义一个简单的字符串类 )#include#define N 10class mystring char str N ; int maxsize ; int last ; public: mystring ( ) ; mystring ( const char * ) ; mystring operator + ( const mystring & ) const ;

60、 mystring & operator += ( const mystring & ) ; mystring & operator = ( const char * ) ; bool operator ( const mystring & ) const ; bool operator = ( const mystring & ) const ; char & operator ( int ) ; friend istream & operator ( istream & , mystring & ) ; friend ostream & operator ( ostream & , mys

61、tring & ) ; 注意:注意:将形参定义为指向常量的指针、常对象引用,目将形参定义为指向常量的指针、常对象引用,目的是防止在函数中修改该形参对象的成员数据。的是防止在函数中修改该形参对象的成员数据。注意:注意:当成员函数中无需修改当前当成员函数中无需修改当前对象的成员数据时,可定义对象的成员数据时,可定义为为const成员函数,这样做成员函数,这样做目的是:防止在函数中发生目的是:防止在函数中发生误操作,出现修改成员数据误操作,出现修改成员数据时,编译将给出错误信息。时,编译将给出错误信息。 34 /构造函数,将新创建的字符串对象初始化为空串构造函数,将新创建的字符串对象初始化为空串 m

62、ystring : mystring ( ) maxsize = N ; str 0 = 0 ; last = 0 ; /构造函数,用构造函数,用C语言风格的字符串来初始化新创建的字符串对象语言风格的字符串来初始化新创建的字符串对象 mystring : mystring ( const char *s ) /当当s所指向的字符串过长时,需截尾处所指向的字符串过长时,需截尾处理理 maxsize = N ; int i = 0 ; while ( ( i = maxsize ) last = i-1 ; str last = 0 ; /截尾截尾 /重载运算符重载运算符+,将两个字符串对象拼接产

63、生第三个字符串对象,将两个字符串对象拼接产生第三个字符串对象 mystring mystring : operator + ( const mystring & ms ) const mystring t ; int i = 0 , k = 0 ; while ( ( i = t . maxsize ) t . last = i-1 ; t . str t . last = 0 ; return t ; /截尾截尾 k = 0 ; while ( ( i = t . maxsize ) t . last = i-1 ; t . str t . last = 0 ; /截尾截尾 return t

64、 ; 35/重载运算符重载运算符+=,将一个字符串对象拼接到当前字符串对象的尾部,将一个字符串对象拼接到当前字符串对象的尾部 mystring & mystring : operator += ( const mystring & ms ) int i = last , k = 0 ; while ( ( i = maxsize ) last = i-1 ; str last = 0 ; /截尾截尾 return *this ; /重载运算符重载运算符=,将,将C语言风格的字符串赋值给当前字符串对象语言风格的字符串赋值给当前字符串对象 mystring & mystring : operato

65、r = ( const char * s ) int i = 0 ; while ( ( i = maxsize ) last = i-1 ; str last = 0 ; /截尾截尾 return *this ; /重载运算符重载运算符 ,返回当前字符串对象中某下标处字符的引用,不检查是否越界,返回当前字符串对象中某下标处字符的引用,不检查是否越界 char & mystring : operator ( int k ) return str k ; 36/重载运算符重载运算符,比较两个字符串对象的大小,比较两个字符串对象的大小bool mystring : operator ( const

66、 mystring &ms ) const int i = 0 , k ; do k = str i - ms . str i ; i+ ; while ( k = 0 & i last & i 0 ) return true ; if ( i != last & i = ms . last ) return true ; return false ; /重载运算符重载运算符=,比较两个字符串对象是否相等,比较两个字符串对象是否相等bool mystring : operator = ( const mystring &ms ) const int i = 0 , k ; do k = str

67、 i - ms . str i ; i+ ; while ( k = 0 & i last & i ,实现字符串对象的整体输入,超出对象容量时做截尾处理,实现字符串对象的整体输入,超出对象容量时做截尾处理istream & operator ( istream & in , mystring & ms ) int i = 0 ; char c ; c = in . get( ) ; while ( ( i = ms . maxsize ) ms . last = i-1 ; ms . str ms . last = 0 ; /截尾截尾 else ms . last = i ; ms . str

68、 ms . last = 0 ; return in ; /重载运算符重载运算符,实现字符串对象的整体输出,实现字符串对象的整体输出 ostream & operator ( ostream & out , mystring & ms ) out ms . str ; return out ; 38void main ( ) mystring s1( “ABCD” ) , s2( “1234567” ) , s3 ; cout “s1=” s1 “ns2=” s2 “ns3=” s3 endl ; s3 = s1 + s2 ; cout “s1=” s1 “ns2=” s2 “ns3=” s3

69、 endl ; s2 += s1 ; cout “s1=” s1 “ns2=” s2 endl ; cout s1 ; cout “s1=” s1 endl ; s1 = “ABCDEFGHIJ” ; cout “s1=” s1 “ns1 3 =” s1 3 endl ; s1 3 = 8 ; cout “s1=” s1 “ns1 3 =” s1 3 endl ; s1 = “ABCD” ; s2 = “A2ED” ; cout “s1=” s1 “ns2=” s2 endl ; cout s2 )=” s2) endl ; cout “( s1=s2 )=” (s1=s2) s2 )=1(

70、s1=s2 )=039C+标准库中的标准库中的string类类l标准字符串类标准字符串类string : string 类提供了类提供了C+面向对象风格的字符串典型操作,面向对象风格的字符串典型操作, string类的声明和实现包含在类的声明和实现包含在头文件头文件 中(名字空间为中(名字空间为std)。)。注意:不在头文件注意:不在头文件 string.h 和和 cstring 中,中,这两个头文件中包含的是这两个头文件中包含的是C语言风格的字符串处理函数。语言风格的字符串处理函数。 可将可将 string 类当作基本数据类型一样使用,而不必了解其内部的具体实现,只需要类当作基本数据类型一样

71、使用,而不必了解其内部的具体实现,只需要知道知道 string 类提供的接口函数即可。类提供的接口函数即可。lstring 类的构造函数:类的构造函数: 默认构造:默认构造: string( ); 功能:将新创建的功能:将新创建的 string 类对象初始化为空串。类对象初始化为空串。 带参构造:带参构造: string ( char * s ); 功能:使用功能:使用C语言风格的字符串语言风格的字符串 s 来初始化新创建的来初始化新创建的 string 类对象。类对象。 拷贝构造:拷贝构造: string ( string & str ); 功能:使用已有的功能:使用已有的 string 类

72、对象类对象 str 来初始化新创建的来初始化新创建的 string 类对象。类对象。40C+标准库中的标准库中的string类类lstring 类对象类对象 str 中某元素的访问:中某元素的访问: 重载运算符重载运算符 : str k 功能:返回功能:返回 string 类对象类对象 str 中下标中下标 k 处元素的引用,不检查是否越界。处元素的引用,不检查是否越界。 成员函数成员函数at( ): str.at ( k ) 功能:返回功能:返回 string 类对象类对象 str 中下标中下标 k 处元素的引用,检查是否越界。处元素的引用,检查是否越界。lstring 类对象之间的运算:类

73、对象之间的运算: 重载运算符重载运算符+: str1 + str2 功能:返回由两个功能:返回由两个string 类对象类对象 str1 和和 str2 拼接而成的第三个拼接而成的第三个 string 类对象。类对象。 重载运算符重载运算符+=: str1 += str2 功能:将功能:将 string 类对象类对象 str2 拼接到拼接到 str1 的尾部,然后返回对象的尾部,然后返回对象 str1。 重载运算符重载运算符=: str1 = str2 功能:将功能:将 string 类对象类对象 str2 赋值给赋值给 str1,然后返回对象然后返回对象 str1。41C+标准库中的标准库中

74、的string类类lstring 类对象之间的关系运算:类对象之间的关系运算: 重载关系运算符:重载关系运算符: str1 str2 、 str1 = str2 str1 str2 、 str1 和和 str 、 cout str 功能:实现功能:实现 string 类对象类对象 str 的整体输入和输出。的整体输入和输出。 非成员函数非成员函数getline( ): getline( cin , str ) /字符串提取以字符串提取以n结束结束 getline( cin , str , ch ) /字符串提取以字符串提取以 ch 结束结束 功能:实现功能:实现 string 类对象类对象 s

75、tr 的整体输入。的整体输入。42C+标准库中的标准库中的string类类lstring 类中常用的成员函数:类中常用的成员函数: 格式:格式: str . substr ( pos , len ) 返回返回 string 类对象类对象 str 中的某子串,从中的某子串,从 pos 位置开始,长度为位置开始,长度为 len 的子串。的子串。 格式:格式: str . empty ( ) 检查检查 string 类对象类对象 str 是否为空串,返回布尔值。是否为空串,返回布尔值。 格式:格式: str . length ( ) 返回返回 string 类对象类对象 str 中字符串的长度。中字

76、符串的长度。 格式:格式: str . insert ( pos , str2 ) 将将 string 类对象类对象 str2 插入到插入到 str 的的 pos 位置处。位置处。 格式:格式: str . erase ( pos , len ) 将将 string 类对象类对象 str 中从中从 pos 位置开始,删除长度为位置开始,删除长度为 len 的子串。的子串。 格式:格式: str . find ( str2 ) 返回返回 str2 首次在首次在 str 中出现时的下标(索引)。中出现时的下标(索引)。 格式:格式: str . find ( str2 , pos ) 返回返回 s

77、tr2 首次在首次在 str 中出现时的下标(索引)中出现时的下标(索引) ,从,从 str 中中 pos 位置开始查找。位置开始查找。 格式:格式: str . c_str ( ) 返回由返回由 string 类对象类对象 str 转换而成的转换而成的 C语言风格的字符串。语言风格的字符串。43【例】【例】( C+标准库中的标准库中的 string 类)类)#include #include using namespace std ;void main ( ) string s1( “ABCD” ) , s2( “1234567” ) , s3 ; cout “s1=” s1 “ns2=”

78、s2 “ns3=” s3 endl ; s3 = s1 + s2 ; cout “s1=” s1 “ns2=” s2 “ns3=” s3 endl ; s2 += s1 ; cout “s1=” s1 “ns2=” s2 endl ; cout s1 ; cout “s1=” s1 endl ; s1 = “ABCDEFGHIJ” ; cout “s1=” s1 “ns1 3 =” s1 3 endl ; s1 3 = 8 ; cout “s1=” s1 “ns1 3 =” s1 3 endl ; s1 = “ABCD” ; s2 = “A2ED” ; cout “s1=” s1 “ns2=” s2 endl ; cout s2 )=” s2) endl ; cout “( s1=s2 )=” (s1=s2) s2 )=1( s1=s2 )=044

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号