运算符重载
【学习要点】
1.理解多态性的概念和实现。
①编译时多态性是通过函数重载、运算符重载实现的。
②运行时多态性是通过类的继承+虚函数实现的。
2.掌握运算符重载的作用和规则。
①在C++中可根据需要对运算符赋予多种含义,以配合用户自定义的类类型。
②运算符重载是通过定义运算符重载函数 operator运算符(实现的。
3.掌握双目、单目运算符重载为成员函数的方法。
4.掌握双目、单目运算符重载为友元函数的方法。
5.掌握重载为成员函数、重载为友元函数的区别:
①友元函数与成员函数不同,它不是类的成员,没有this指针。
②运算符 =、()、[ ]、—> 不能重载为友元函数,只能重载为成员函数。
③运算符插入”<<”、提取”>>” 只能重载为友元函数。
6.掌握几个特殊运算符“++”、“--”、“=”、“[ ]”、“<<”、“>>”的重载。
7.掌握类型转换函数。
8.掌握自定义字符串类。
9.掌握C++标准库中的string类的使用。
------------------------------------------------------------------------------------------------------------------------------------------------
【例题分析】
1.下面程序中的错误有几处?
#include
class C
{ int x , y ;
public:
C ( { }
C ( int a , int b : x( a , y( b { }
C operator@ ( C a
{ C temp ; temp.x=x+a.x ; temp.y=y+a.y ; return temp ; }
int operator# ( C a
{ return ( x * y ; }
friend C operator= ( C a
{ x=a.x ; y=b.y ; return *this ; }
void show(
{ cout << "x=" << x <<"\ty=" << y << endl ; }
};
void main(
{ C a( 2 , 3 , b( 2 , 3 , c ;
(a+b.show( ; c=a ; c.show( ;
}
【答案】3
【解析】
①函数C operator@ (C a ; 运算符重载是允许用户重新定义运算符的含义,但此运算符必须是C++系统预定义的,而“@”不是C++预定义的运算符,应换成“+”。
②函数int operator# (C a ; 符号#不允许重载,应换成“*”,另外形参C a也不需要。
③函数friend C operator = (C a ; 赋值运算符“=”只能重载为成员函数,不能重载为友元函数,故将friend删去。其次,返回类型最好是 C & 。
2.编写程序:存放在my Vector.cpp文件中,包含内容如下:
①定义向量类Vector。私有成员数据有:存放向量在三条坐标轴上投影值的x、y、z。公有成员函数有:可设置向量中x、y、z值的成员函数void set( float a=0, float b=0, float c=0 ;可输出向量中x、y、z值的成员函数void show( ;构造函数Vector ( float a=0 , float b=0 , float c=0 ;构造函数Vector( float v[ 3 ] ;两个赋值运算符“=”重载成员函数Vector & operator=( Vector v 、Vector & operator=( float v[ 3 ] 。
②将实现两个向量之间加、减、乘运算的三个独立函数声明为Vector类的友元函数:
friend Vector operator+( Vector v1 , Vector v2 ;
friend Vector operator-( Vector v1 , Vector v2 ;
friend float operator*( Vector v1 , Vector v2 ;
③编写main(函数去测试,完成向量间的运算。
【提示】若向量a在三条坐标轴上的投影为a x , a y , a z,则表达式a = { a x , a y , a z } 称为向量a的坐标表达式。设有两个向量a和b,它们之间的加、减、乘的运算公式为:
a +
b = { ax +bx , ay +by , az+bz }
a -
b = { ax -bx , ay -by , az-bz }
a *
b = ax *bx + ay *by + az *bz
将运算符“+”、“-”、“*”和“=”重载,实现向量间的加、减、乘、赋值运算。
【答案】编写程序如下:
#include
#include
class Vector
{ float x , y , z;
public:
Vector( float a=0 , float b=0 , float c=0
{ x=a ; y=b ; z=c ; }
Vector( float v[ 3 ]
{ x=v[0] ; y=v[1] ; z=v[2] ; }
void set( float a=0 , float b=0 , float c=0
{ x=a ; y=b ; z=c ; }
void show(
{ cout << x << 'i' ;
cout << ( (y<0 ? '-' : '+' << fabs(y << 'j' ;
cout << ( (z<0 ? '-' : '+' << fabs(z << 'k' << endl ; }
Vector & operator=( Vector v ;
Vector & operator=( float v[ 3 ] ;
friend Vector operator+( Vector v1 , Vector v2 ;
friend Vector operator-( Vector v1 , Vector v2 ;
friend float operator*( Vector v1 , Vector v2 ;
};
Vector & Vector:: operator=( Vector v
{ x=v.x ; y=v.y ; z=v.z ; return *this ; }
Vector & Vector:: operator=( float v[ 3 ]
{ x=v[0] ; y=v[1] ; z=v[2] ; return *this ; }
Vector operator+( Vector v1 , Vector v2
{ Vector temp ;
temp.x=v1.x+v2.x ; temp.y=v1.y+v2.y ; temp.z=v1.z+v2.z ; return temp ; }
Vector operator-( Vector v1 , Vector v2
{ Vector temp ;
temp.x=v1.x-v2.x ; temp.y=v1.y-v2.y ; temp.z=v1.z-v2.z ;
return temp ; }
float operator*( Vector v1 , Vector v2
{ return ( v1.x*v2.x + v1.y*v2.y + v1.z*v2.z ; }
void main(
{ float a[ ] = { 1 , 2 , 3 } ;
Vector v1( a , v2( 4 , 5 , 6 , v3( 7 , 8 , 9 , v4 , v5 ;
v4 = v1 + v2 ; v4.show( ;
v5 = v3 - v1 ; v5.show( ;
cout << "v1*v2=" << v1*v2 << endl ;
}
【解析】定义向量类,并对各运算符进行重载。本程序采用友元函数重载“+”、“-”、“*”运算符,在此也可采用成员函数重载,从程序可读性考虑,一般认为双目运算符,重载为友元函数更好些。但重载“=”运算符必须用成员函数。
------------------------------------------------------------------------------------------------------------------------------------------------
【思考题】
㈠选择题
1.下面运算符中,不能重载的是______。
A.?:
B.+
spanC.*
D.<=
【答案】???
【提示】C++中不能被重载的运算符有“::”、“?:”、“.”、“.*”、“sizeof”
2.下面运算符中,不能重载的是______。
A.&&
B.[ ]
C.::
D.new
【答案】???
3.关于运算符重载,下面描述中正确的是______。
A.运算符重载可以改变操作数的个数
B.运算符重载可以改变优先级
C.运算符重载可以改变结合性
D.运算符重载不可以改变语法结构
【答案】???
【提示】运算符重载不能改变操作数的个数、运算符的优先级、运算符的结合性和运算的语法结构。
4.友元重载运算符obl>ob2 被C++编译器解释为______。
A.operator>( obl , ob2
B.>( ob1 , ob2
C.ob2.operator>( ob1
D.ob1.operator>( ob2
【答案】???
【提示】友元函数重载运算符的调用形式:operator<运算符>( <参数1>,<参数2>
等价于表达式:<参数1> <运算符> <参数2>
5.若a+b运算需通过成员函数实现“+”运算符重载,下面描述中正确的是______。
A.a必须为该类对象,b可为其它数据类型
B.a和b都必须为该类对象
C.b必须为该类对象,a可为其它数据类型
D.a和b均可为其它数据类型
【答案】???
【提示】成员函数实现a+b时,编译器解释为:a.operator(b,因此左操作数a必须为该类对象,否则无法实现成员函数的调用,而右操作数可以是该类的对象,也可以是其它数据类型。
6.M A是一个类名,下面重载运算符的成员函数原型中不正确的是______。
A.MA operator-( ;
B.MA operator-( MA ;
C.MA operator-( MA & ;
D.MA operator-( MA , MA ;
【答案】???
【提示】运算符“-”可以是单目运算符的“负”运算,也可以是双目运算符的“减”运算,因此成员函数实现时,可以不带参数(实现一元运算,也可以带一个参数(实现二元运算,但不可能是两个参数。
7.有下面类定义,并在类外对“++”运算符重载函数进行定义,其中不正确的是______。
class Point
{ int x , y ;
public:
Point operator++( ;
};
A.Point Point:: operator++( { x++ ; y++ ; return *this ; }
B.Point Point:: operator++( { x+=5 ; y+=5 ; return *this ; }
C.Point Point:: operator++( { x-- ; y-- ; return *this ; }
D.Point Point:: operator++( int n { x+=n ; y+=n ; return *this ; }
【答案】???
【提示】函数定义时的参数声明必须与函数原型中的参数声明一致。答案D与函数原型中的参数不一致,所以是错误的。尽管在答案B和答案C中,函数的功能和实际理解的自增概念不一样,但函数定义是正确的,运算符重载本身就是给运算符重新定义功能。
8.对list类进行逻辑运算符“==”重载,下面重载函数声明中正确的是______。
A.list & list:: operator==( const list &a ;
B.list list:: operator==( const list &a ;
C.bool & list:: operator==( const list &a ;
D.bool list:: operator==( const list &a ;
【答案】???
9.有下面类定义,若主函数中有定义:fun m , c , d ; 则执行语句c=++m; 编译器将其中的++m解释为______。
class fun
{public: fun operator+=( fun ;
friend fun operator++( fun & ; };
A.c.operator++( m ;
B.m=operator++( m ;
C.m.operator++( m ;
D.operator++( m ;
【答案】???
10.在上题中,若执行语句d+=m; 编译器将其解释为______。
A.d=operator+=( m ;
B.m=operator+=( d ;
C.d.operator+=( m ;
D.m.operator+=( d ;
【答案】???
11.有下面类定义,若类外执行语句a=b+c; 编译器将其中的 b+c 解释为:
operator +( b,c ; 则下面描述中正确的是______。
class Com
{……
friend Com operator+( …… ; };
A.a、b、c都必须是Com的对象。
B.a、b都必须是Com的对象。
C.a必须是Com的对象,而b和c中只要有一个是Com的对象即可。
D.b、c都必须是Com的对象。
【答案】???
------------------------------------------------------------------------------------------------------------------------------------------------
㈡填空题
1.双目运算符重载为类的成员函数时,其左操作数必须是______,而右操作数可以是______。
【提示】将双目运算符重载为类的成员函数时,由于this指针在非静态成员函数操作对象时都作为第一个隐式参数传递了对象,它充当了双目运算符的左操作数,而该成员函数的形参则表示双目运算符的右操作数。因此左操作数必须是该类的对象,而右操作数可以是类型与形参类型兼容的数据。
2.运算符重载必须保持其原来的优先级、______、______。
【提示】运算符重载不能改变操作数的个数、运算符的优先级、运算符的结合性、运算符的语法结构。
3.运算符“+”重载后,若希望该运算符满足交换性,可将其重载为______。
【提示】
①成员函数重载时,其左操作数必须是类的对象,如果右操作数是一个其它数据类型,就不可以实现交换。
②友元函数重载时,只需要两个操作数中,其中一个是类的对象,这两个操作数都作为参数,所以可满足运算符“+”的可交换性。即执行sl+s2和s2+sl的结果是相同的,从而满足运算符“+”的交换性。
4.运算符重载一种是通过成员函数来实现,另一种是通过______来实现。
5.当用成员函数重载双目运算符时,运算符的左操作数必定是______。
------------------------------------------------------------------------------------------------------------------------------------------------
㈢改写程序题
1.复数类Complex,将运算符“+”以成员函数形式重载,实现两复数相加。试采用友元函数改写该程序中的运算符重载函数。
#include
class Complex
{ float real , image ;
public:
Complex( float r=0 , float i=0 : real( r , image( i { }
Complex operator+( Complex &c
{ return Complex( real+c.real , image+c.image ; }
void show(
{ if ( image >= 0 cout << real << '+' << image << 'i' << endl ;
else cout << real << '-' << (-image << 'i' << endl ; }
};
void main(
{ Complex c1( 1 , 2 , c2( -3 , -4 , c3 ;
c3 = c1 + c2 ;
c3.show( ;
}
改写程序如下:
【答案】???
------------------------------------------------------------------------------------------------------------------------------------------------
㈣编程题
1.编写程序:存放在myComplex.cpp文件中,包含内容如下:
①定义复数类Complex。私有成员数据有:存放实部、虚部值的real、image。公有成员函数有:可设置复数实部、虚部值的成员函数 void set( float r=0 , float i=0 ;可按“3+5i”(或”3-5i”)格式输出复数的成员函数 void show( ;构造函数Complex ( float r=0 , float i=0 。
②用成员函数方式重载运算符:“前置++”、“后置++”、“前置- -”、“后置- -”,实现复数的增量和减量运算。
③用友元函数方式重载运算符:“+”、“-”、“+=”、“-=”,“==”、“!=”,实现复数的双目运算。
④编写main(函数去测试Complex类。
编写程序如下:
【答案】???
2.编写程序:改写第1题,要求如下:
◆将第1题中的②改用友元函数方式重载运算符:“前置++”、“后置++”、“前置- -”、“后置- -”,实现复数的增量和减量运算。
◆将第1题中的③改用成员函数方式重载运算符:“+”、“-”、“+=”、“-=”,“==”、“!=”,实现复数的双目运算。
编写程序如下:
【答案】???
3.编写程序:存放在myStudent.cpp文件中,包含内容如下:
①定义学生类Student。私有成员数据有:存放学号、姓名、成绩值的 id、name、score。公有成员函数有:可设置学生值的成员函数void set( int i=0 , char *na =” ” , int
s=0 ;可按“学号=04081111 姓名=张小笑成绩=99” 格式输出的成员函数 void show( ;构造函数Student ( int i=0 , char *na =” ” , int s=0 。
②用友元函数方式重载关系运算符:大于“>”、小于“<”,实现两个学生的比较运算,学生之间的比较按其成绩比较,“成绩高的学生”大于“成绩低的学生”。
friend bool operator> ( Student &s1 , Student &s2 ;
friend bool operator< ( Student &s1 , Student &s2 ;
③用友元函数方式重载运算符:提取“>>”、插入“<<”,实现学生数据的整体输入和输出。
friend istream & operator>> ( istream &in , Student &s ;
friend ostream & operator<< ( ostream &out , Student &s ;
④编写main(函数:定义学生数组Student [ 6 ] ,实现学生数据的键盘输入、降序排序、并将排序后的学生数据输出到显示器、文件(Student.txt )中各1份。
编写程序如下:
【答案】???
4.编写程序:
㈠自定义一个字符串类 mystring,其声明部分存放在mystring.h头文件中,其成员函数的实现部分存放在mystring.cpp文件中,定义内容如下:
★成员数据:
① char s [ N ] ; 用于存放字符串的数组容器,其中 N 为常量
② int size ; 数组中最多可容纳的元素数, size = N
③ int last ; 数组中已用元素的最大下标,空串时 last = 0
★成员函数:
①构造函数: mystring ( ;
mystring ( char * ;
mystring ( mystring & ; //可省略不写
②析构函数: ~mystring ( ; //可省略不写
③成员重载运算符: mystring operator + ( mystring & ;
mystring operator + ( char * ;
mystring & operator += ( mystring & ;
mystring & operator += ( char * ;
mystring operator = ( mystring & ; //可省略不写
mystring & operator = ( char * ;
bool operator < ( mystring & ;
bool operator < ( char * ;
bool operator == ( mystring & ;
bool operator == ( char * ;
char & operator [ ] ( int ;
④友元重载运算符:istream & operator >> ( istream & , mystring & ;
ostream & operator << ( ostream & , mystring & ;
㈡编写main(函数对字符串类 mystring进行测试。
编写程序如下:
【答案】???
4.(选做)编写程序:存放在my Birth.cpp文件中,包含内容如下:
①定义生日类Birth。私有成员数据有:存放年、月、日值的year、month、day。公有成员函数有:可设置生日的成员函数 void set( int y=0 , int m=0 , int d=0 ;可按“生日
=1990/12 /06” 格式输出生日的成员函数 void showBirth( ;可按“年龄= 20” 格式输出年龄的成员函数 void showAge( ;构造函数 Birth( int y=0 , int m=0 , int d=0 ;构造函数Birth( char *s ,其参数值为以“yyyy/mm/dd” 形式给出的字符串。
②定义类型转换成员函数 operator int ( ; 将生日数据转换为整型数据年龄。
③用友元函数重载运算符“>”、“<”、“==”,实现两个生日之间的比较运算。如:表达式Birth("2002/10/01" > Birth("2001/01/10",表示2002年10月1日在2001年1月10日之后;表达式Birth("2005/10/01 == Birth(5, 10, 1,表示两个生日是同一天。
④编写main(函数去测试Birth类。
【提示】
◆库函数 time( 原型:long time( long * t ;
功能:提取当前时间,即从1970/01/01的00:00:00开始到当前的秒数,
返回该值,并存放到长整型变量 t 中。
注意:使用该函数需包含 / 头文件。
◆库函数 ctime(原型:char * ctime( const long * t ;
功能:将长整型变量 t中以秒计的时间转换为日期时间格式的字符串。
注意:使用该函数需包含 / 头文件。
◆库函数 atoi( 原型:int atoi( const char * t ;
功能:将字符串转换为整型数。
注意:使用该函数需包含 / 头文件。
◆库函数 itoa( 原型:char * itoa( int val , char *s ;
功能:将整型数val转换为字符串,存放到字符数组s中(最多17字节)。
注意:使用该函数需包含 / 头文件。
◆例: #include
#include
#include
#include
void main (
{ long t ;
cout << time( &t << endl ; //此处输出:1230342429
cout << t << endl ; //此处输出:1230342429
char datetime[ 30 ] ;
cout << ctime ( &t ; //此处输出:Sat Dec 27 09 :50 :16 2008
strcpy ( datetime , ctime ( &t ;
cout << datetime ; //此处输出:Sat Dec 27 09 :50 :16 2008
cout << datetime+20 ; //此处输出:2008
int val = atoi( datetime+20 ;
cout << val << endl ; //此处输出:2008
char year [ 6 ] ;
itoa( val , year , 10 ;
cout << year << endl ; //此处输出:2008
}
编写程序如下:
【答案】???
5.(选做)编写程序:改写第5题,要求如下:
◆将第4题的③改用成员函数方式重载运算符“>”、“<”、“==”,实现两个生日之间的比较运算。
编写程序如下:
【答案】???
------------------------------------------------------------------------------------------------------------------------------------------------
运算符重载基础概念练习题 1、下列运算符中, ()运算符在C++中不能重载。 A = B () C :: D delete 2、下列运算符中, ()运算符在C++中不能重载。 A ?: B [] C new D && 3、下列关于C++运算符函数的返回类型的描述中,错误的是()。 A 可以是类类型 B 可以是int类型 C 可以是void类型 D 可以是float类型 4、下列运算符不能用友元函数重载的是()。 A + B = C * D << 5、在重载运算符函数时,下面()运算符必须重载为类成员函数形式。 A + B - C ++ D -> 6、下列关于运算符重载的描述中,正确的是()。 A 运算符重载可以改变运算符的操作数的个数 B 运算符重载可以改变优先级 C 运算符重载可以改变结合性 D 运算符重载不可以改变语法结构 7、友元运算符obj>obj2被C++编译器解释为()。 A operator>(obj1,obj2) B >(obj1,obj2) C obj2.operator>(obj1) D obj1.oprator>(obj2) 8、在表达式x+y*z中,+是作为成员函数重载的运算符,*是作为非成员函数重载的运算符。下列叙述中正确的是()。 A operator+有两个参数,operator*有两个参数 B operator+有两个参数,operator*有一个参数 C operator+有一个参数,operator*有两个参数 D operator+有一个参数,operator*有一个参数 9、重载赋值操作符时,应声明为()函数。 A 友元 B 虚 C 成员 D 多态 10、在一个类中可以对一个操作符进行()重载。 A 1种 B 2种以下 C 3种以下 D 多种 11、在重载一个运算符时,其参数表中没有任何参数,这表明该运算符是()。
C++习题参考答案 第1章面向对象程序设计概论 一、名词解释 抽象封装消息 【问题解答】 面向对象方法中的抽象是指对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程。 面向对象方法中的封装就是把抽象出来的对象的属性和行为结合成一个独立的单位,并尽可能隐蔽对象的内部细节。 消息是面向对象程序设计用来描述对象之间通信的机制。一个消息就是一个对象要求另一个对象实施某种制作的一个请求。 二、填空题 (1)目前有面向过程的结构化程序设计方法和面向对象的程序设计方法两种重要的程序设计方法。 (2)结构化程序设计方法中的模块由顺序、选择和循环3种基本结构组成。(3)在结构化程序设计方法中,程序可表示为程序=数据结构+算法。而面向对象的程序设计方法,程序可表示为程序=对象+消息。 (4)结构化程序设计方法中的基本模块是过程。而面向对象程序设计方法中的基本模块是类。 (5)面向对象程序设计方法具有抽象性、封装性、继承性和多态性等特点。 三、选择题(至少选一个,可以多选) (1)面向对象程序设计着重于( B )的设计。 A. 对象 B. 类 C. 算法 D. 数据 (2)面向对象程序设计中,把对象的属性和行为组织在同一个模块内的机制叫做( C )。 A. 抽象 B. 继承 C. 封装 D. 多态 (3)在面向对象程序设计中,类通过( D )与外界发生关系。 A. 对象 B. 类 C. 消息 D. 接口 (4)面向对象程序设计中,对象与对象之间的通信机制是( C )。 A. 对象 B. 类 C. 消息 D. 接口 (5)关于C++与C语言的关系的描述中,( D )是不对的。 A. C语言是C++的一个子集 B. C语言与C++是兼容的 C. C++对C语言进行了一些改进 D. C++和C语言都是面向对象的 【结果分析】 C语言是面向过程的。C++语言是一种经过改进的更为优化的C语言,是一种混合型语言,既面向过程也面向对象。 (6)面向对象的程序设计将数据结构与( A )放在一起,作为一个相互依存、不可分割的整体来处理。 A. 算法 B. 信息 C. 数据隐藏 D. 数据抽象 (7)下面( A )不是面向对象系统所包含的要素。 A. 重载 B. 对象 C. 类 D. 继承 【结果分析】
1.概念填空题 1.1运算符重载是对已有的运算符赋予多重含义,使同一个运算符在作用于不同类型对象时导致不同的行为。运算符重载的实质是函数重载,是类的多态性特征。 1.2可以定义一种特殊的类型转换函数,将类的对象转换成基本数据类型的数据。但是这种类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。类类型转换函数既没有参数,也不显式给出返回类型。类类型函数中必须有return 表达式的语句返回函数值。一个类可以定义多个类类型转换函数。 1.3运算符重载时其函数名由operator运算符构成。成员函数重载双目运算符时,左操作数是对象,右操作数是函数参数。 2.简答题 2.2简述运算符重载的规则。 2.2简述重载单目运算符++、--,前置和后置时的差别。 2.3 C++中重运算符是否都可以重载?是否都可以重载成类的成员函数?是否都可以重载成类的友元函数? 2.4 构造函数作为类型转换函数的条件是什么。 3.选择题 3.1在下列运算符中,不能重载的是(B) A.! B. sizeof C. new D. delete 3.2 不能用友员函数重载的是(A)。 A.= B.== C.<= D.++ 3.3下列函数中,不能重载运算符的函数是(B)。 A.成员函数 B.构造函数 C.普通函数 D.友员函数 3.4如果表达式++i*k时中的”++”和”*”都是重载的友元运算符,则采用运算符函数调用格式,该表达式还可表示为(B)。 A.operator*(i.operator++(),k) B.operator*(operator++(i),k) C.i.operator++().operator*(k) D.k.operator*(operator++(i)) 3.5已知在一个类体中包含如下函数原型:VOLUME operator-(VOLUME)const;下列关于这个函数的叙述中,错误的是(B )。 A.这是运算符-的重载运算符函数 B.这个函数所重载的运算符是一个一元运算符 C.这是一个成员函数 D.这个函数不改变数据成员的值 3.6在表达式x+y*z中,+是作为成员函数重载的运算符,*是作为非成员函数重载的运算符。下列叙述中正确的是(C )。 A.operator+有两个参数,operator*有两个参数 B.operator+有两个参数,operator*有一个参数 C.operator+有一个参数,operator*有两个参数 D.operator+有一个参数,operator*有一个参数 4.写出下列程序运行结果 4.1#include
走进3D的世界 -- C++中用运算符重载实现矩阵运算 作者:周军 矩阵(Matrix)无处不在,我们的生活中到处都能找到矩阵的身影,然而此处我不想把这个定义放大,我们只讨论线性代数中的矩阵,我们要用它们来完成我们的3D变换。为什么矩阵可以完成3D变换呢?下面,我们就来介绍矩阵是如何变换坐标的: 设空间中有一坐标(x,y,z),如果我们想把它变换成另一坐标(x,’y’,z’),我们可以进行如下操作: = (x’,y’,z’,1) 这就是矩阵的妙用了。它在复杂处理变换的时候表现得尤为突出。假设我们想要把一个物体先沿z轴旋转角thetaZ,再沿x轴旋转角thetaX,我们可以进行如下操作(pseudo-code): obj*=rotX(thetaX)*rotZ(thetaZ); 注意:矩阵的乘法是不可逆的,而且我们要按变化顺序的逆序进行乘法,具体推导见计算几何相关书籍。 下面,我们进入正题:如何再C++中用重载运算符的方法来进行矩阵运算以完成线性变换呢?我们需要变换坐标,所以很自然地,我们需要一个向量(Vector)类;同时我们要进行
为直观、人性化,我选用了运算符重载这以技巧而不是简单地调用函数,下面请看我的具体实现:
以上便是CVector类的具体实现,我想对C++和线性代数有所了解的读者都能很清楚地理解这段代码,在次不累述。 上述代码的成员函数实在类外定义的,如果读者在实践中为了提高速度可以把这些成员函数定义在类内以起到内联函数的作用,可以省去参数压栈、出栈时的时间。 下面是CMatrix类的具体实现:
是不是也很好理解呢?哈哈,这就是用运算符重载的好处。不过这种方法也确实有它的不足,而且这个不足在游戏编程中是致命的,那就是效率不高,这也正是为什么Microsoft 在DirectX中也使用难看的一般函数调用来完成矩阵运算的原因。影响速度的主要原因是在使用运算符+、-、*、/等时,程序会在每次运算时创建临时对象再将临时对象返回,对于重复多次的矩阵运算来说,这无疑成为了一笔庞大的额外开销(好在现在的计算机的处理速度还算快)。但注意:在使用+=、-=、*=、/=时不会有上述问题,因为在使用这些运算符时程序只需要修改第一个对象不需要创建并返回临时对象。所以在能使用+=、-=、*=、/=时尽量不要使用单一的=、-、*、/运算符。 好了,这两个类我们已经封装好了,下面还有什么呢?是的,忘了向大家交代旋转矩阵了:
Task8-1 /* 1. 定义一个复数类Complex,重载运算符“+”,使之能用于复数的加法运算。将运算符函数重载为非成员、非友元的普通函数。编写程序,求两个复数之和*/ #include /*2. 定义一个复数类Complex,重载运算符“+”、”-“、”*”、”/”, 使之能用于复数的加、减、乘、除。运算符重载函数作为Complex类的成员函数,编程,分别求两个复数之和差积商。 */ #include 二、运算符重载(运算符重载的基本概念、运算符重载方法、运算符重载规则、特殊运算符重载和类型转换) 单选题10道: 1、假定要对类AB定义加号操作符重载成员函数,实现两个AB类对象的加法,并返回相加结果,则该成员函数的声明语句为( B )。 A. AB operator+(AB& a,AB& b) B. AB operator+(AB& a) C. operator+(AB a) D. AB &operator+( ) 2、关于运算符重载,下面的叙述错误的是()。 A.运算符预定义的操作数个数不能改变 B.重载不能改变运算符的优先级顺序 C.参数的类型没有限制 D.尽量使其与原意保持一致 3、在一个类中可以对一个操作符进行(D )重载。 A. 1种 B. 2种以下 C. 3种以下 D. 多种 4、重载赋值操作符时,应声明为(C )函数。 A. 友元 B. 虚 C. 成员 D. 多态 5、要在类对象使用运算符,以下不必被重载的运算符是( A )。 A. [] B. = C. ++ D. -- 6、下列运算符中,不能重载的是(C ) A.new B.() C.::D.&& 7、在表达式x+y*z中,+ 是作为成员函数重载的运算符,*是作为非成员函数重载的运算符。下列叙述中正确的是( A )。 A)operator+有两个参数,operator*有两个参数 B)operator+有两个参数,operator*有一个参数 C)operator+有一个参数,operator*有两个参数 D)operator+有一个参数,operator*有一个参数 8、友元运算符obj1>obj2被C++编译器解释为()。 A) operator>(obj1,obj2) B) >(obj1,obj2) C) obj1.operator>(obj2) D) obj2.operator>(obj1) 9、已知某个类的友元函数重载了+=和-,a,b,c是该类的对象,则“a+=b-c”被C++编译器解释为()。 A) operator+=(a,operator-(b,c)) B) a.operator+=(b.operator-(c)) C) operator+=(a,b.operator-(c)) D) a.operator+=(operator-(b,c)) 10、下列运算符中,必须使用成员函数进行重载的是()。 A) == B) = C) >> D) ++ 填空题10道: 1、多数运算符既能作为类的成员函数重载,也能作为类的非成员函数重载,但运算符“[]”只能作为类的函数重载。 2、加法运算符“+”和赋值运算符“=”都重载之后,“+=”也被重载了。 3、单目运算符作为类的成员函数重载时形参。 4、利用成员函数对二元运算符重载时,其右操作数为。 5、重载运算符函数的函数名由关键字引出。 6、运算符的重载归根结底是的重载。 7、后缀自增自减运算符定义时带有一个。 . 《面向对象程序设计》习题 班级:学号:姓名:名单序号:成绩: 第7章运算符重载和多态性 一、选择题(共30分,每题1分) 1.下列运算符中,()运算符在C++中不能重载。 A.?: B.[] C. new D.++ 2.友元重载运算符obj1>obj2被C++编译器解释为()。 A.operator >(obj1,obj2) B.>(obj1,obj2) C.obj2.operator >(obj1) D.obj1.operator >(obj2) 3.重载赋值操作符时,应声明为()函数。 A.友元B.虚C.成员D.多态 4.在重载一个运算符时,其参数表中没有任何参数,这表明该运算符是()。 A. 作为友元函数重载的1元运算符 B. 作为成员函数重载的1元运算符 C. 作为友元函数重载的2元运算符 D. 作为成员函数重载的2元运算符5.在重载一运算符时,若运算符函数的形参表中没有参数,则不可能的情况是()。 A. 该运算符是一个单目运算符。 B. 该运算符函数有一个隐含的参数this。 C. 该运算符函数是类的成员函数。 D. 该运算符函数是类的友元函数。 6. 关于运输符重载,下列表述中正确的是()。 A.C++已有的任何运算符都可以重载 B.运算符函数的返回类型不能声明为基本数据类型 . C.在类型转换符函数的定义中不需要声明返回类型 D.可以通过运算符重载来创建C++中原来没有的运算符 7. C ++流中重载的运算符>>是一个()。 A. 用于输出操作的非成员函数 B. 用于输出操作的成员函数 C. 用于输入操作的非成员函数 D. 用于输入操作的成员函数 8. 若要对Data类中重载的加法运算符成员函数进行声明,下列选项中正确的是()。 A. Data +(Data); B. Data operator+(Data); C. Data +operator(Data); D. operator +(Data, Data); 9. 下列运算符中哪些是不能够被重载的()。 A. .,.*,sizeof,::,?: B. ++,--,new,= = C. new,delete,>=,[ ] D. +,-,=,delete 10. 在名为BigNumber类的类体中对运算符函数double进行如下声明: operator double(BigNumbe); 函数声明中有一个明显的错误,这个错误就是()。 A.参数表中不应该有任何参数 B.缺少对函数返回类型的说明 C.参数声明中缺少参数变量 D.函数声明中缺少函数体 11. 下列关于运算符重载的描述中,正确的是()。 A. 运算符重载成为成员函数时,若参数表中无参数,重载是一元运算符 B. 一元运算符只能作为成员函数重载 C. 二元运算符重载成为非成员函数时,参数表中有一个参数 运算符重载 一.单项选择题 1.下列运算符中,运算符在C++中不能重载。 A.?: B.+ C. D.<= 解:C++中不能被重载的运算符有:·,一,::,?:。本题答案为A。 2.下列运算符中,运算符在C++中不能重载。 A.&& B.[] C.:: D.new 解:c++中不能被重载的运算符有:·,·+,::,?:。本题答案为c。 3.下列关于运算符重载的描述中,是正确的。 A.运算符重载可以改变操作数的个数 B.运算符重载可以改变优先级 C.运算符重载可以改变结合性 D.运算符重载不可以改变语法结构 解:运算符重载不能改变操作数的个数、运算符的优先级、运算符的结合性和运算程的语法结构。本题答案为D。 4.友元运算符objl>obj2被C++编译器解释为。 A.operator>(objl,obj2) B.>(obj1,obj2) C.obj2.operator:>(obj1) D.objl.operator>(obj2) 解:重载为友元函数的运算符的调用形式如下: operator<运算符>(<参数1>,<参数2>) 等价于:<参数1><运算符><参数2> 本题答案为A。 5.现需要对list类对象使用的逻辑运算符“==”重载,以下函数声明是正确的。 A、list & list::operator==(const list &a); B、list list::operator==(const list &a); C、bool & list::operator==(const list &a); D、bool list::operator==(const list &a); 6. 以下类中分别说明了“+=”和“++”运算符重载函数的原型。如果主函数中有定义: fun m,c,d;,那么,执行语句c=m++; 时,编译器把m++解释为: (33) A) c.operator++(m); B) m=operator++(m); C) m.operator++(m); D) operator++(m); class fun { public: .. .. .. fun operator +=(fun ); friend fun operator ++(fun &,int); }; 答案:D 7. 在第33题中,当执行语句d+=m; 时,C++编译器对语句作如下解释: (34) A. d=operator+=(m); B. m=operator+=(d); C. d.operator+=(m); D. m.operator+=(d); 答案:C 8. 设有以下类定义,其中说明了“+”运算符重载函数的原型。这是一个友元函数,当类 一、运算符重载的规则 运算符重载规则如下: ①、C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符。 ②、重载之后运算符的优先级和结合性都不会改变。 ③、运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。 不能重载的运算符只有五个,它们是:成员运算符“.”、指针运算符“*”、作用域运算符“::”、“sizeof”、条件运算符“?:”。 运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。 运算符重载为类的成员函数的一般语法形式为: 函数类型 operator 运算符(形参表) { 函数体; } 运算符重载为类的友元函数的一般语法形式为: friend 函数类型 operator 运算符(形参表) { 函数体; } 其中,函数类型就是运算结果类型;operator是定义运算符重载函数的关键字;运算符是重载的运算符名称。 当运算符重载为类的成员函数时,函数的参数个数比原来的操作个数要少一个;当重载为类的友元函数时,参数个数与原操作数个数相同。原因是重载为类的成员函数时,如果某个对象使用重载了的成员函数,自身的数据可以直接访问,就不需要再放在参数表中进行传递,少了的操作数就是该对象本身。而重载为友元函数时,友元函数对某个对象的数据进行操作,就必须通过该对象的名称来进行,因此使用到的参数都要进行传递,操作数的个数就不会有变化。 运算符重载的主要优点就是允许改变使用于系统内部的运算符的操作方式,以适应用户自定义类型的类似运算。 一般说来,单目运算符最好被重载为成员;对双目运算符最好被重载为友元函数,双目运算符重载为友元函数比重载为成员函数更方便此,但是,有的双目运算符还是重载为成员函数为好,例如,赋值运算符。 二、运算符重载为成员函数 对于双目运算符B,如果要重载B为类的成员函数,使之能够实现表达式oprd1 B oprd2,其中oprd1为类A的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型。经过重载后,表达式oprd1 B oprd2 就相当于函数调用 oprd1.operator B(oprd2). 运算符重载复习题 1. 重载赋值操作符时,应声明为( ) A. 友元函数 B. 虚函数 C. 成员函数 D. 多态函数 2.关于重载的描述,正确的是( ) A.函数重载只能在成员函数之间进行 B.函数重载只能在全局函数之间进行 C.函数重载可以在基类和派生类之间进行 D.函数重载必须要求同名的函数的形参类型和个数都完全一致,返回值类型无所谓 3.下列运算符中不能重载的是( )。 A.∷(域运算符) B.+ (正) C.++ (自增) D.*(指针) 4. 派生类的对象对它的基类成员中() A. 公有继承的公有成员是可以访问的 B. 公有继承的私有成员是可以访问的 C. 公有继承的保护成员是可以访问的 D. 私有继承的公有成员是可以访问的 5 不能重载的运算符是() A. ?: B. [ ] C. new D. && 6. C++中不能重载的运算符是( ) A. new B. += C. sizeof D. && 7.重载函数是( ) A.以函数参数来区分,而不用函数的返回值来区分不同的函数 B.以函数的返回值来区分,而不用函数参数来区分不同的函数 C.参数表完全相同而返回值类型不同的两个或多个同名函数 D.参数表和返回值类型中至少有一个不同的两个或多个同名函数 8.对于运算符重载,说法正确的是( ) A.运算符如果被重载为非成员函数,那么对象就不能利用这个运算符重载函数进行操作 B.运算符重载函数可能既不是成员函数,也不是友元函数 C.用户每定义一个类,系统会自动提供一个赋值运算符重载函数,所以完全不 必考虑重载赋值运算符函数 D.一个类的虚函数不能调用运算符重载函数 9. C++中不能重载的运算符是( ) 《面向对象程序设计》习题 班级:学号:姓名:名单序号:成绩: 第7章运算符重载和多态性 一、选择题(共30分,每题1分) 1.下列运算符中,()运算符在C++中不能重载。 A.?: B.[] C. new D.++ 2.友元重载运算符obj1>obj2被C++编译器解释为()。 A.operator >(obj1,obj2) B.>(obj1,obj2) C.obj2.operator >(obj1) D.obj1.operator >(obj2) 3.重载赋值操作符时,应声明为()函数。 A.友元B.虚C.成员D.多态 4.在重载一个运算符时,其参数表中没有任何参数,这表明该运算符是()。 A. 作为友元函数重载的1元运算符 B. 作为成员函数重载的1元运算符 C. 作为友元函数重载的2元运算符 D. 作为成员函数重载的2元运算符5.在重载一运算符时,若运算符函数的形参表中没有参数,则不可能的情况是()。 A. 该运算符是一个单目运算符。 B. 该运算符函数有一个隐含的参数this。 C. 该运算符函数是类的成员函数。 D. 该运算符函数是类的友元函数。 6. 关于运输符重载,下列表述中正确的是()。 A.C++已有的任何运算符都可以重载 B.运算符函数的返回类型不能声明为基本数据类型 C.在类型转换符函数的定义中不需要声明返回类型 D.可以通过运算符重载来创建C++中原来没有的运算符 7. C ++流中重载的运算符>>是一个()。 A. 用于输出操作的非成员函数 B. 用于输出操作的成员函数 C. 用于输入操作的非成员函数 D. 用于输入操作的成员函数 8. 若要对Data类中重载的加法运算符成员函数进行声明,下列选项中正确的是()。 A. Data +(Data); B. Data operator+(Data); C. Data +operator(Data); D. operator +(Data, Data); 9. 下列运算符中哪些是不能够被重载的()。 A. .,.*,sizeof,::,?: B. ++,--,new,= = C. new,delete,>=,[ ] D. +,-,=,delete 10. 在名为BigNumber类的类体中对运算符函数double进行如下声明: operator double(BigNumbe); 函数声明中有一个明显的错误,这个错误就是()。 A.参数表中不应该有任何参数 B.缺少对函数返回类型的说明 C.参数声明中缺少参数变量 D.函数声明中缺少函数体 11. 下列关于运算符重载的描述中,正确的是()。 第4章运算符重载 4.1 什么是运算符重载 所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。 运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。如:+可以对int、float、double的数据进行加法运算。 现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。譬如,能否用“+”号进行两个复数、两个点的相加。在C++中不能在程序中直接用运算符“+”对复数进行相加运算。用户必须自己设法实现复数相加。 例如用户可以通过定义一个专门的函数来实现复数相加。见下例。 //例4.1 通过函数来实现复数相加。 #include C++习题参考答案 第1章面向对象程序设计概论 一、名词解释 抽象封装消息 【问题解答】 面向对象方法中得抽象就是指对具体问题(对象)进行概括,抽出一类对象得公共性质并加 以描述得过程、 面向对象方法中得封装就就是把抽象出来得对象得属性与行为结合成一个独立得单位,并 尽可能隐蔽对象得内部细节。 消息就是面向对象程序设计用来描述对象之间通信得机制。一个消息就就是一个对象要求另一个对象实施某种操作得一个请求。 二、填空题 (1) 目前有面向过程得结构化程序设计方法与面向对象得程序设计方法两种重要得程序设计方法。 (2) 结构化程序设计方法中得模块由顺序、选择与循环3种基本结构组成。 (3) 在结构化程序设计方法中,程序可表示为程序=数据结构+算法; 而面向对象得程序设计 方法,程序可表示为程序=对象+消息。 (4) 结构化程序设计方法中得基本模块就是过程; 而面向对象程序设计方法中得基本模块就是类。 (5) 面向对象程序设计方法具有抽象性、封装性、继承性与多态性等特点、 三、选择题(至少选一个,可以多选) (1) 面向对象程序设计着重于( B )得设计。 A。对象B。类C、算法D、数据 (2) 面向对象程序设计中,把对象得属性与行为组织在同一个模块内得机制叫做( C )。A、抽象 B。继承 C。封装D. 多态 (3) 在面向对象程序设计中,类通过( D )与外界发生关系。 A、对象 B. 类C、消息D。接口 (4) 面向对象程序设计中,对象与对象之间得通信机制就是( C )。 A、对象 B。类 C. 消息 D、接口 (5) 关于C++与C语言得关系得描述中,( D )就是错误得、 A、 C语言就是C++得一个子集B、C语言与C++就是兼容得 C. C++对C语言进行了一些改进 D. C++与C语言都就是面向对象得 【结果分析】 C语言就是面向过程得。C++语言就是一种经过改进得更为优化得C语言,就是一种混合型语言,既面向过程也面向对象、 (6) 面向对象得程序设计将数据结构与( A )放在一起,作为一个相互依存、不可分割得整体来处理。 A、算法 B。信息C、数据隐藏 D、数据抽象 (7) 下面( A )不就是面向对象系统所包含得要素。 A。重载 B、对象 C. 类 D。继承 【结果分析】 面向对象=对象+类+继承+消息+多态 (8) 下面说法正确得就是( BC )。 A。将数据结构与算法置于同一个函数内,即为数据封装 B。一个类通过继承可以获得另一个类得特性 C。面向对象要求程序员集中于事物得本质特征,用抽象得观点瞧待程序 D。同一消息为不同得对象接受时,产生得行为就是一样得,这称为一致性 【结果分析】 运算符重载(operator overload) 是c++的一个重要的新特性,它使得程序员把c++运算符定义扩展到操作数是对象的情况.运算符重载的目的是使c++程序更加直观,更易懂. 运算符重载和普通的重载一样: 作用域相同,函数名字相同,但参数不同(参数个数,参数的类型) , 注意如果函数名字相同,参数相同但函数的返回值类型不同这不是重载,这是错误! 返回值类型operator 被重载的运算符(参数...){函数的实现} 具体的例子网上有很多, 我的重点是一些我们在写重载中易忽略的一些小问题. 有时候我们的程序在多数情况下是对的但有时也总有一些出乎我们意料的情况: 请看下面这个程序: #include C++中预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型,也需要有类似的运算操作。例如: class complex { public: complex(double r=0.0,double I=0.0){real=r;imag=I;} void display(); private: double real; double imag; }; complex a(10,20),b(5,8); “a+b”运算如何实现?这时候我们需要自己编写程序来说明“+”在作用于complex类对象时,该实现什么样的功能,这就是运算符重载。运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同类型的行为。 运算符重载的实质是函数重载。在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用达标函数,这个过程爱编译过程中完成。 一、运算符重载的规则 运算符重载规则如下: ①、C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符。 ②、重载之后运算符的优先级和结合性都不会改变。 ③、运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。 不能重载的运算符只有五个,它们是:成员运算符“.”、指针运算符“*”、作用域运算符“::”、“sizeof”、条件运算符“?:”。 运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。 运算符重载为类的成员函数的一般语法形式为: 函数类型 operator 运算符(形参表) { 函数体; } 运算符重载为类的友元函数的一般语法形式为: friend 函数类型 operator 运算符(形参表) { 函数体; } 其中,函数类型就是运算结果类型;operator是定义运算符重载函数的关键字;运算符是重载的运算符名称。 当运算符重载为类的成员函数时,函数的参数个数比原来的操作个数要少一个;当重载为类 第11章运算符重载 一.单项选择题 1.下列运算符中,运算符在C++中不能重载。 A.?: B.+ C. D.<= 解:C++中不能被重载的运算符有:·,一,::,?:。本题答案为A。 2.下列运算符中,运算符在C++中不能重载。 A.&& B.[] C.:: D.new 解:c++中不能被重载的运算符有:·,·+,::,?:。本题答案为c。 3.下列关于运算符重载的描述中,是正确的。 A.运算符重载可以改变操作数的个数 B.运算符重载可以改变优先级 C.运算符重载可以改变结合性 D.运算符重载不可以改变语法结构 解:运算符重载不能改变操作数的个数、运算符的优先级、运算符的结合性和运算程的语法结构。本题答案为D。 4.友元运算符objl>obj2被C++编译器解释为。 A.operator>(objl,obj2) B.>(obj1,obj2) C.obj2.operator:>(obj1) D.objl.operator>(obj2) 解:重载为友元函数的运算符的调用形式如下: operator<运算符>(<参数1>,<参数2>) 等价于:<参数1><运算符><参数2> 本题答案为A。 5.现需要对list类对象使用的逻辑运算符“==”重载,以下函数声明是正确的。 A、list & list::operator==(const list &a); B、list list::operator==(const list &a); C、bool & list::operator==(const list &a); D、bool list::operator==(const list &a); 6. 以下类中分别说明了“+=”和“++”运算符重载函数的原型。如果主函数中有定义: fun m,c,d;,那么,执行语句c=m++; 时,编译器把m++解释为: (33) A) c.operator++(m); B) m=operator++(m); C) m.operator++(m); D) operator++(m); class fun { public: .. .. .. fun operator +=(fun ); friend fun operator ++(fun &,int); }; 答案:D 7. 在第33题中,当执行语句d+=m; 时,C++编译器对语句作如下解释: (34) A. d=operator+=(m); B. m=operator+=(d); C. d.operator+=(m); D. m.operator+=(d); 答案:C 8. 设有以下类定义,其中说明了“+”运算符重载函数的原型。这是一个友元函数,当类 实验21 运算符重载 一、实验目的和要求 1.理解运算符重载的作用。 2.掌握实现运算符重载的方法及几种特殊运算符的重载格式。 3.进一步锻炼针对类的编程能力。 二、实验准备 ?知识点 1.运算符重载定义的一般格式、基本概念。 2.运算符函数重载的两种形式。 3.通过成员函数实现运算符重载的一般格式。 4.通过友元函数实现运算符重载的一般格式。 5.”++”运算符的重载。 6.”=”赋值运算符的重载。 ?课前练习题 1.重载运算”+”,实现a+b运算,则。 A.a必须为对象,b可为整数或实数B.a和b必须为对象 C.b必须为对象,a可为整数或实数D.a和b均可为整数或实数 2.在C++中,运算符的重载有两种实现方法,一种是通过成员函数来实现,另一种则通过_________来实现。 3.不能重载的5个运算符是:______、______、______、______、_________。 4.重载赋值运算符必须通过________函数实现。 5.用成员函数实现前置”--”运算符重载的一般格式为:_______________________________。6.用友元函数实现后置”--”运算符重载的一般格式为:_______________________________。 ?分析 1.有以下程序: #include 第13章 一、选择题 1、下面关于运算符重载的说法中,错误的是()。 A、可以对C++所有运算符进行重载 B、运算符重载保持固有的结合性和优先级顺序 C、运算符重载不能改变操作数的个数 D、在运算符函数中,不能使用缺省的参数值 2、下列运算符能被重载的是()。 A、:: B、?: C、. D、% 3、下列叙述正确的是()。 A、运算符重载函数只能是一个成员函数 B、运算符重载函数既可以是一个成员函数,也可以是友元函数 C、运算符重载函数只能是一个非成员函数 D、运算符重载函数只能是友元函数 4、下列叙述不正确的是()。 A、利用成员函数重载二元运算符时,参数表中的参数必须为两个 B、利用成员函数重载二元运算符时,成员函数的this指针所指向的对象作为运算符的左操作数 C、利用成员函数重载二元运算符时,参数表中的参数作为此运算符的右操作数 D、运算符重载时不能改变运算符的语法结构 5、为了区分一元运算符的前缀和后缀运算,在后缀运算符进行重载时,额外添加一个参数,其类型是()。 A、void B、char C、int D、float 6、下列能正确重载运算符的友元函数原型是()。 A、friend B operator?: ( ); B、friend B operator+(int x); C、friend B operator+(B b); D、friend B operator+(B b, B a); 7、下列叙述正确的是()。 class B { int a,b; public: B(int aa=0, int bb=0) { a=aa; b=bb; } B operator+ ( int x ) //A { B r; r.a=a+x; r.b=b+x; 8.4 运算符重载 运算符重载是非常重要的功能,因为它使我们能够使用像+、–、*这样的标准C++运算符,来处理自定义数据类型的对象。该功能允许我们编写重新定义特定运算符的函数,从而使该运算符处理类对象时执行特定的动作。例如,我们可以重新定义>运算符,从而使该运算符用于前面看到的CBox类对象时,如果第一个实参的体积比第二个大,就返回true。 运算符重载功能不允许我们使用新的运算符,也不允许我们改变运算符的优先级,因此运算符的重载版本在计算表达式的值时优先级与原来的基本运算符相同。运算符的优先级表可以在本书第2章和MSDN库中找到。 虽然我们不能重载所有运算符,但限制不是特别严格。下面给出不能重载的运算符: 作用域解析运算符 :: 条件运算符 ?: 直接成员访问运算符 . sizeof运算符 sizeof 解除对指向类成员的指针的引用运算符 .* 任何其他运算符都是可以重载的,这给予我们相当大的灵活性。显然,确保标准运算符的重载版本与原来的正常用途一致,或者至少在操作上相当直观,是合适的想法。如果为某个类重载的+运算符却执行使类对象相乘的操作,这可能就不是明智的做法。理解运算符重载机制如何工作的最好方法是完成一个示例,因此下面为CBox类实现刚才提到的大于运算符>。 8.4.1 实现重载的运算符 为了给某个类实现重载的运算符,我们必须编写特殊的函数。假设在类定义内重载>运算符的函数是CBox类的成员,则该函数的声明如下所示: class CBox { public: bool operator>(CBox& aBox) const; // Overloaded 'greater than' // Rest of the class definition... }; 这里的单词operator是个关键字。该关键字结合运算符符号或名称,本例中是>,将定义一个运算符函数。本例中的函数名是operator>()。在运算符函数的声明中,关键字和运算符本身之间有无空格都行,前提是没有歧义。歧义出现在运算符是名称而非符号的时候,比如new或delete。如果写成不加空格的operatornew和operatordelete,则它们都是合法的普通函数名。因此,如果要编写这些运算符的运算符函数,则必须在关键字operator和运算符名称之间加个空格。注意,我们将函数声明为const,因为该函数不修改本类的数据成员。 在operator>()运算符函数中,运算符的右操作数由函数形参定义,左操作数由this指针隐式定义。因此,如果有下面这条if语句: if(box1 > box2) cout << endl << "box1 is greater than box2"; 则括弧中的表达式将调用重载的运算符函数,它与下面这个函数调用等价: box1.operator>(box2); 表达式中的CBox对象与运算符函数形参之间的对应关系如图8-3所示。运算符重载题目
运算符重载知识题
运算符重载练习题
C++运算符重载
第十章 运算符重载 复习题
第7章 运算符重载-习题
运算符重载
C++第13章答案
运算符重载注意
C++运算符重载讲解与经典实例 (2)
第11章 运算符重载 习题解答
C++实验21 运算符重载
第13章习题
运算符重载