运算符重载
一.单项选择题
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.设有以下类定义,其中说明了“+”运算符重载函数的原型。这是一个友元函数,当类
外有语句a=b+c;访问这个友元函数时,C++ 编译器把对语句a=b+c;解释为:
operator +(b,c)
其中:(35)
A. a,b,c C. a,c
都必须是Com 的对象
都必须是Com 的对象
B. a,b
D. b,c
都必须是
都必须是
Com 的对象
Com 的对象
class Com
{ ... ...
friend Com operator +(... ...); };
答案: B
二.填空题
1.利用成员函数对双目运算符重载,其左操作数为,右操作数为。
解:将双目运算符重载为类的成员函数时,由于this指针在每次非静态成员函数操作对
象时都作为第一个隐式参数传递给对象,因此它充当了双目运算符的左操作数,而该成员函数的形参则表示双目运算符的右操作数。本题答案为:this指针成员函数参数。
2.运算符重载仍然保持其原来的优先级、和。
解:运算符重载不能改变操作数的个数、运算符的优先级、运算符的结合性和运算符的语法结构。本题答案为:结合性语法结构。
3.为了满足运算符“+”的可交换性,必须将其重载为。
解:以友元函数方式重载运算符可满足运算符“+”的可交换性,因为两个操作数都作为
参数,例如,有以下程序:
#include
class Sample
{
int n;
public:
Sample(){}
Sample(int i){n=i;}
friend Sample operator+(Sample,Sample);
void disp() {cout<<“ n=” < } Sample operator+(sample s1,Sample s2) { return sample(S1.n+s2.n); } void main() { Sample S1(2),s2(5),s3; cout<<” S1:”; S1.disp(); cout<<” s2:”; s2.disp(); s3=S1+S2 ; cout<<” s3:”; s3 .disp(); S3=S2+S1; cout<< ” s3:”; s3.disp(); } 程序执行结果如下: 从中看到,执行 sl+s2 和 s2+sl 的结果是相同的,从而满足运算符“ +”的交换性。所以本题答案为:友元函数。 4 .在c++中,运算符的重载有两种实现方法,一种是通过成员函数来实现,另一种则通过 (4)来实现。 答案:友元 5. 当用成员函数重载双目运算符时,运算符的左操作数必定是:(5) 答案:对象 三.程序分析题 1.以下程序的执行结果是 #include class Sample { 。 int n; public: Sample(){) Sample(int m){n=m int &operator--(int) { n--; return n; } ; ) void disp() { cout<<”rl=”< } void main() { Sample s(10) (S--)++; S .disp(); ; } 解:该程序中,类 Sample 的重载”一”运算符的成员函数返回Sample 对象的私有数据成员 n 的引用。在main() 函数中执行 (s--)++;语句时,先调用重载成员函数,使S 对象的n 值减 1,这时返回的是S 对象的 n 的引用,再执行++运算,也就是对s 对象的 n 值执行++运算,所以s 对象的 11 值保持不变。程序的执行结果为:n=lO 。 2.以下程序的执行结果是: #include class Sample { . h> private: int x; public: Sample(){x=0; } void disp(){cout<< void 0perator++(){x+=10”x=”< ; } } } void main() { Sample obj obj . disp();; obj++; cout<<“执行。 obj . disp(); bj++ 之后”< } 解:在类该对象的Sample 中设计运算符重载成员函数,使运算符“ x 增 10。本题答案为: ++”作为于Sample 类对象时, x=0 执行obj++ 之后 x=10 3.阅读下面的程序,在空白处填写出程序运行后的结果。 #include class complex { float real,imag, public: complex(float r,float i){real=r;imag=i;} complex(){real=O; imag=O ; } void print(); friend complex operator+(complex a,complex b); friend complex operator一(complex a,complex b); friend complex operator‘ (complex a,complex b); friend complex operator/(complex a,complex b); } void complex { ::print() cout< if(imag>O)cout<<”+”; if(imag!:0) cout< } complex operator+(complex a,complex b) { complex temp; temp . real=a . real+b . real ; temp . imag=a. imag+b. imag; return temp; } complex operator-(complex a,complex b) { complex temp; temp . real=a . real-b.real; temp . imag=a. imag-b . imag; return temp; } complex operator *(complex a,complex b) { complex temp temp . real ; : a. real*b. real-a. imag *b. imag; temp . imag=a. real *b.imag+a.imag *b.real; return temp; } complex operator/(complex a,complex b) { complex temp; float tt; tt=l/ (b .real ‘ b.real+b .imag 。 b. imag) ; temp. real=(a . real*b . real+a . imag*b . imag)*tt; temp. imag=(b . real*a . imag-a . real*b . imag)*tt; return temp; } void main() { complex c1(2. 3, 4. 6) , c2(3 . 6, 2. 8) , c3; c1. print(); c2. print(); c3=c1+c2; c3. print(); c3=c1-c2; c3. print(); c3=c1*c2; c3. print(); c3=c1 / c2; c3. print(); } 程序运行结果为: 2. 3+4. 6i 3. 6+2. 8i (1) (2) (3) (4) 解: (1) 、 (2) 、 (3) 和 (4) 分别是 2.3+4 .6i 和 3.6+2.8i 除的结果。本题答案为:(1)5.9+7.4i (4)A.1.01731+0.486538i。两个复数相加、相减、相乘和相(2)-1.3+1.8i(3)-4.6+23i; 四.简答题 1.说明以下类date #include static int dys[]={31,28, 31,30, 31,30, 31,31, 30, 31, 30, 31) ;c1ass date { int mo ,rda, ryr; public: date(int m,int d,int y){mo=m date(){} void disp(){cout< { ;da=d; yr=y ; } < ,int day) //运算符重载友元函数 date dt; dt . mo=d. mo; dt . yr=d . yr ; day+=d.da; while(day>dys[dt { . mo-1]) day-=dys[dt. mo-1] ; if(++dt. mo==13) { dt. mo=1; dt. yr++ ; } } dt . da=day;. return dt; } } void main() { date dl(2 d2=dl+365 d2 . disp(), 10, 2003) , d2;; ; } 解:类date 含有 mo、 da 和) , r 3个私有数据成员,分别存放一个日期的月份、日号和年份。其成员函数有:两个构造函数,disp0成员函数用于显示日期,“ +”运算符重载为计算指定日期加上指定天数后的日期。本程序输出2003 年 2 月 10 日加上 365 天后的日期,结果为:2/ 10/ 2004。 2.说明以下类Words 的功能,并给出程序执行结果。 #include #include class Words { char *str public: Words(char *s) { ; str=new char[strlen(s)+1] strcpy(str, s) ; ; } void disp(){cout< char operator[](int i) { ; } if(str[i]>=’ A’ && str[i]<='Z') return char(str[i]+32);else if(str[i]>='a'&&str[i]<='z') // 4' return char(str[i]-32) else //其他字符 return str[i];// ; 大写字母 写字母 } } void main() { int i; char *s=”Hello”; Words word(s); word . disp(); for(i=0; i cout< cout< } 解:Words 类含有一个私有数据,其成员函数有:一个构造函数,disp()函数用于输出str , 下标运算符重载函数用于将指定下标的字母大小写互换,其他字符时不变。本程序的输出结果如下: Hell() heLL() 3.有以下两个程序,分析它们的执行结果有什么不同。 程序 l : #include class Point { int x,y; public: Point(){x=y=0;} Point(int i,int j){x=i Point operator+(Point) ; y=j ; ;} void disp() ( cout<<” (” < Point Point::operator+(Point P) { this->x+=P.x;this->y+=p. y; return *this; } void main() { Point pl(2, 3) , p2(3 , 4) ,p3; cout<<” pl :”; p1.disp(); cout<<” p2:”; p2.disp(); p3=pl+p2; cout<<”执行 p3=pl+p2 后” < cout<<” pl :”, p1.disp(); cout<<” p2:”; p2.disp(); cout<<” p3:”; p3.disp(); } 程序 2: #include class Point{ int x,Y; public : Point(){x=y=O;} Point(int i, int j){x=i, y=j ; } Point operator+(Point); void disp f){cout<<”( ” < Point Point ::operator+(Point P) { Point s; s .x=x+p .x; s . y=y+p. y; return s; } void main() { Point pl(2, 3) , p2(3 , 4) ,p3; cout<<” pl :”; p1.disp(); cout<<” p2:”; p2.disp(); p3=pl+p2; cout<<”执行 p3=pl+p2 后” < cout<<” pl :”; p1.disp(); cout<<” p2:”; p2.disp(); cout<<” p3:”; p3.disp(); } 解:这两个程序中的实现,只是程序l 部对象。 main 函数完全相同,类 的运算符重载函数使用this Point中的运算符重载均采用成员函数方式 指针,而程序 2 的运算符重载函数使用局 p3=pl+p2 等价于 p3=p1. operator+(p2)。对于程序this->x+=p.x;this->y十一p.y;语句,修改p l对象的语句,将pl 对象赋给p3。所以p1 和 p3 两个对象的p1=p1+p2,p3: pl ,其运行结果如下: pl :(2 , 3) p2 :(3 , 4) l , this指针指向p1 对象,执行 x 和 y 成员值,执行 return*this;x、 Y 值相同,即p3=pl+p2 等价于 执行 p3=pl+p2 后 P1:(5,7) p2 :(3 , 4) P3:(5,7) 对于程序2,执行运算符重载函数,Point s;语句定义一个对象,s.x=x+p.x;s.y=y+p.y;语句用于修改 s 对象的 x、 Y 值, ret % il~l s ;语句返回该对象,赋给 p3,而 pl 和 p2 对象不改变。其运行结果如下: pl :(2 , 3) p2 :(3 , 4) 执行 p3=pl+p2 后 pl :(2 , 3) p2 :(3 , 4) p3 :(5 , 7) 五.完善程序题 1. 本程序调用构造函数实现字符串对象的初始化。调用重载运算符” +”把两个字符串拼接,并通 过重载运算符“ >”来实现字符串的比较运算。 #include #include class string { char *str; public: string(char *s=0) { if(_(14)_){str=new char[strlen(s)+1]; strcpy(__(15)__);} else str=0; } friend string operator+(string &,string &); int operator>(string &); void show(){ if(str)cout< }; string operator+(string &s1,string &s2) { string t; t.str=____(16)_____; strcat(t.str,s2.str); ______(17)_______; } int string::operator>(string &s) { if(strcmp(____(18)_____)>0)return 1; else return 0; } void main(void) { string s1("southeast university"),s2("mechanical department"); string s3; s3=s1+s2; s1.show(); s2.show(); s3.show(); cout<<(s1>s2)<<'\n'; } 答案: (14) s (15) str,s (16) s1.str (17) return t (18) str,s.str 六.上机题(一)改错题(二)编程题 1.定义一个计数器类Counter ,对其重载运算符“解:计数器类Counter含有一个私有整型数据成员值增 l 。程序如下:+”。 n,“ +”运算符重载为使对象的n #include class Counter { . h> int n; public: Counter(){n=O;}// Counter(int i){n=i;} Counter operator+(Counter c)// {// 默认构造函数 构造函数 运算符重载函数 Counter temp; temp.n=n+c.n; return temp; } void disp() { cout<<” n=” < void main() { Counter cl(5) c3=c1+c2; , c2(10), c3 ; c1 c2 c3. disp(). disp(). disp() ; ; ; } 2. C++ 在运行期间不会自动检查数组是否越界。设计一个类能够检查数组是否越界。 解:设计一个类 Words,下标运算符重载为:判断指定的下标是否越界,越界时显示相应的错误信息,未越界时返回该下标的字符。程序如下: #include #inc]ude class Words { int len char *str ; ; // str // 所指字符串的长度 字符串指针 public: Words(char *s)//构造函数{ str=new char[strlen(s)+1]; strcpy(str, s) ; len=strlen(s); } char operator[](int n) { if(n>len-1) { cout<< return ”数组下标越界” ; ‘’;//返回一个特殊字符 } else return*(str+n); } void disp(){cout< } void main() { Words word(” Goodbye” ); word . disp(); cout<< ”位置 0:”; cout< cout<<”位置15:”; cout< } 3.设计一个日期类Date ,包括年、月、日等私有数据成员。要求实现日期的基本运算,如某日期加上天数、某日期减去天数、两日期相差的天数等。 解:在 Date 类中设计如下重载运算符函数: Date operator+(int days) Date operator~(int days):返回某日期加上天数得到的日期:返回某日期减去天数得到的日期 · int operator-(Date&b):返回两日期相差的天数 在实现这些重载运算符函数时调用以下私有成员函数: · leap(int):判断指定的年份是否为闰年 · dton(Date &):将指定日期转换成从0 年 O月 O日起的天数 .ntod(int):将指定的0 年 O月 O日起的天数转换成对应的日期 程序如下: #include int day_tab[2][12]={{31,28,31,30,3l,30,3l,3l,30,31,30,31),{31 , 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}} ; // day_tab二维数组存放各月天数,第一行对应非闰年,第二行对应闰年 class Date { int year,month,day;int leap(int);// int dton(Date&); Date ntod(int);//年,月,日判断是否为闰年 public: Date(){} Date(int Y,int m,int d){ year=y void setday(int d){day=d;} void setmonth(int m){month=m;} void setyear(int y){year=y;} int getday(){return day;} int getmonth(){return month;} int getyear(){return year;} Date operator+(int days) // + {; month=m; day=d; }运算符重载函数 static Date date; int number=dton(*this)+days date=ntod(number); return date; ; } Date operator-(int days)//一运算符重载函数{ Static Date date; int number=dton( *this) number-=days; date=ntod(number); return date; ; } int operator-(data&b)//一运算符重载函数{ int days=dton(*this)-dton(b)-1 return days; ; } void disp()// {cout< 输出日期 ”.”< } int Date::leap(int year) { if(year% 4==0 && year % 100!=0 || year return 1; else //不是闰年 return 0; % 400==0)//是闰年 } int Date::dton(Date)&d)//求从公元0 年 0 月 0 日到 d 日期的天数{ int y,m,days=0; for (y=1;y<=d.year;y++) if(1eap(y))days+=366;else days+=365;////闰年时加 366 天非闰年时加365 天 for(m=0; m if(leap(d . year))days+=day_tab[1][m]; else days+=day_tab[0][m]; days+=d. day; return days; } Date Date:: ntod(int n)//将从公元0 年0 月0 日的天数转换成日期{ int y=l; m=l; d, rest=n,lp; while(1) { if(leap(y)) // if(rest<=366) break else rest-=366;else // IP闰年 if(rest<=365) break else rest-=365;闰年 ; ; y++; } y--; ip=leap(y) while(1) { ; if(ip) else // if(rest>day else break // 闰年 ; tab[1][m-1])rest-=day_tab[1][m-i] ; 非闰年 ; if(rest>day_tab[0][m-1])rest-=day_tab[0][m-1];else break; m++: } d=rest; return Date(y, m,d) ; } void mein() { Date now(2003,10,1),then(2005,6,5); cout<< ” now:”; now. disp(); cout<< ” then :”; then . disp(); cout<< ”相差天数:”<<(then — now)< Date dl=now+1000,d2=now-i000; cout<< ” now+1000:”;dl . disp(); cout<< ” now— 1000 :”; d2. disp(); } 本程序的执行结果如下: now :2003. 10. 1 then:2005.6.5 相差天数: 612 now+1000 : 200 6 . 6.27 now 一 1000 :2001. 1.14 4.定义如下集合类的成员函数,并用数据进行测试。 class Set { int *elem;// int count;// public : Set(); Set(int s[],int n) int find(int x)const Set operator+(const Set Set operator-(const Set Set operator*(const Set void disp();// 存放集合元素的指针 存放集合中的元素个数 ; ;//判断X是否在集合中& ) ;//集合的并集 & ) ; //集合的差集 & ) ; // 集合的交集 输出集合元素 } 解:该类的运算符重载均采用成员函数方式实现。程序如下:#include const int N=100;//集合中最多元素个数 class Set { int * elem;//存放集合元素的指针 int count;//存放集合中的元素个数public: Set(); Set(int S[],int n); int find(int x)const;//判断X是否在集合中 Set operator+(const Set&);//集合的并集 Set operator-(const Set&);//集合的差集 Set operator*(const Set&);//集合的交集 void disp();//输出集合元素 } Set ::Set() //默认构造函数 { elem=NULL; count=O; } Set ::Set(int s[],int n)//初始化构造函数 { int i; elem=new int[n]; for(i=0; i *(elem+i)=s[i]; count=n; } int Set::find(int x)const { int i; for(i=O; i if(*(elem+i)==x) return 1; return 0; } Set Set::operator+(const set &s) { int a[N],i,k; for(i=0; i ; //先将当前集合元素放入 a 数组中 k=count for(i=0; ; i 数组中 s 中不在当前集合中的元素放入a if(find(s. elem[I])) continue ; else { if(k==N-1)break; a[k++]=s .elem[i]; } return Set(a, k);//调用构造函数产生一个无名对象返回} Set Set:: operator-(const Set&s) //集合的差集 { int a[N] for(i=0 ,i , k=0; ; i 组中 s 集合中的元素放入 a 数 if(!s. find(elem[i])) a[k++]=elem[i]; return Set(a, k) ;//调用构造函数产生一个无名对象返回} Set Set:: operator*(const Set &s) //集合的交集 { int a[N] for(i=0 if(s ,k=0, i ; ; i .find(elem[i])) //扫描当前集合中所有元素 return Set(a a[k++]=elem[i] , k) ;// ;//将属于两个集合的元素放在 调用构造函数产生一个无名对象返回 a 数组中 } void Set::disp()//输出集合元素 { int i; for(i=0; i cout<<*(elem+i)<<””; cout< } void main() { int a[]={1,4,2,7,8}; int b[]={2,3,1,6,7,}; Set s1(a,5),s2(b,5),s3; cout<< ”集合 S1:”;s1 . disp(); cout<< ”集合 s2:”; s2 . disp(); S3=s1+S2; cout<< ”并集:”; s3. disp(); S3=s1*S2; cout<< ”交集:”; S3. disp(); S3=s1-s2 ; cout<< ”差集:”; s3. disp()j } 本程序的执行结果如下: 集合 S1:14278 集合 S2:23167 并集:1427836 交集:127 差集:48 5.编写一个程序,重载“+”、“ -”、“ +=”运算符,完成对复数的相应运算。要求:(1)定义复数类以及相应的重载函数; (2)在主函数中定义三个复数对象,并初始化其中的两个; (3)使用初始化过的两个复数,分别进行“+”、“ -”和“ +=”运算,将运算结果赋给第三个复数,并显示之; (4)将计算输出的结果以注释的形式符于程序后面; (5)程序文件名为 myfile1.cpp 。 6.学生管理模拟程序(18分) 【要求】按以下描述和要求建立两个类student 和 manage: class student{//学生类,使用缺省构造函数 friend class manage; private: int xh;// char *xm; //学号姓名 float cj; //成绩 public: student &operator=(student &t); //将 t 数据成员的值拷贝给this对象 ( 深拷贝) }; class manage{ //学生管理类 private: student s[30]; //存放学生信息,最多可有30位学生 int n;//实际学生人数 void swap(student &a,student &b); //交换对象a和b的数据成员 值 public: manage(){n=0;} //学生表构造函数 void newstu(int a,char *b,float c); //在数组s中添加一个学生 //( 为 student 类对象的数据成员赋值 ) void list();// int maxcj(); // 屏幕打印学生清单 找出成绩最高的学生,输出其学号、姓名和成绩,// 返回该学生在数组s中的位置 int minicj(); // void select(); // 找出成绩最低的学生,输出其学号、姓名和成绩, // 返回该学生在数组s中的位置 将成绩最高的学生交换到数组s的第一个元素,//同时将成绩最低的学生交换到s[n-1] }; void manage::swap(student &a, student &b){ //交换对象a和b student temp; temp=a;a=b;b=temp; } 请完成以上未定义函数体的成员函数。 在主程序中定义一个manage类对象,调用成员函数newstu() 向学生表 (s 数组 ) 中添加若干学生。调用成员函数list()在屏幕上输出学生信息。调用成员函数maxcj() 找出成绩最高的学生,调用成员函数minicj()找出成绩最低的学生。调用成员函数 select()按要求将成绩最高的学生交换到数组s的第一个元素,同时将成绩最低的学生交换到s[n-1]。注意实现运算符’ =’号的重载。字符串复制可使用string.h 中包含的 strcpy( )函数。 每个成员函数至少被使用一次。通过多次的函数调用来测试你的程序功能是否达到要 求。 【注意】将源程序以文件名MYF2.cpp存入 Z盘自己的文件夹中。 运算符重载基础概念练习题 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、在重载一个运算符时,其参数表中没有任何参数,这表明该运算符是()。 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中也使用难看的一般函数调用来完成矩阵运算的原因。影响速度的主要原因是在使用运算符+、-、*、/等时,程序会在每次运算时创建临时对象再将临时对象返回,对于重复多次的矩阵运算来说,这无疑成为了一笔庞大的额外开销(好在现在的计算机的处理速度还算快)。但注意:在使用+=、-=、*=、/=时不会有上述问题,因为在使用这些运算符时程序只需要修改第一个对象不需要创建并返回临时对象。所以在能使用+=、-=、*=、/=时尽量不要使用单一的=、-、*、/运算符。 好了,这两个类我们已经封装好了,下面还有什么呢?是的,忘了向大家交代旋转矩阵了: 运算符重载复习题 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++中不能重载的运算符是( ) 二、运算符重载(运算符重载的基本概念、运算符重载方法、运算符重载规则、特殊运算符重载和类型转换) 单选题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、后缀自增自减运算符定义时带有一个。 运算符重载 一.单项选择题 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. 设有以下类定义,其中说明了“+”运算符重载函数的原型。这是一个友元函数,当类 《面向对象程序设计》习题 班级:学号:姓名:名单序号:成绩: 第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. 下列关于运算符重载的描述中,正确的是()。 一、运算符重载的规则 运算符重载规则如下: ①、C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符。 ②、重载之后运算符的优先级和结合性都不会改变。 ③、运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。 不能重载的运算符只有五个,它们是:成员运算符“.”、指针运算符“*”、作用域运算符“::”、“sizeof”、条件运算符“?:”。 运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。 运算符重载为类的成员函数的一般语法形式为: 函数类型 operator 运算符(形参表) { 函数体; } 运算符重载为类的友元函数的一般语法形式为: friend 函数类型 operator 运算符(形参表) { 函数体; } 其中,函数类型就是运算结果类型;operator是定义运算符重载函数的关键字;运算符是重载的运算符名称。 当运算符重载为类的成员函数时,函数的参数个数比原来的操作个数要少一个;当重载为类的友元函数时,参数个数与原操作数个数相同。原因是重载为类的成员函数时,如果某个对象使用重载了的成员函数,自身的数据可以直接访问,就不需要再放在参数表中进行传递,少了的操作数就是该对象本身。而重载为友元函数时,友元函数对某个对象的数据进行操作,就必须通过该对象的名称来进行,因此使用到的参数都要进行传递,操作数的个数就不会有变化。 运算符重载的主要优点就是允许改变使用于系统内部的运算符的操作方式,以适应用户自定义类型的类似运算。 一般说来,单目运算符最好被重载为成员;对双目运算符最好被重载为友元函数,双目运算符重载为友元函数比重载为成员函数更方便此,但是,有的双目运算符还是重载为成员函数为好,例如,赋值运算符。 二、运算符重载为成员函数 对于双目运算符B,如果要重载B为类的成员函数,使之能够实现表达式oprd1 B oprd2,其中oprd1为类A的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型。经过重载后,表达式oprd1 B oprd2 就相当于函数调用 oprd1.operator B(oprd2). 第4章运算符重载 4.1 什么是运算符重载 所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。 运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。如:+可以对int、float、double的数据进行加法运算。 现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。譬如,能否用“+”号进行两个复数、两个点的相加。在C++中不能在程序中直接用运算符“+”对复数进行相加运算。用户必须自己设法实现复数相加。 例如用户可以通过定义一个专门的函数来实现复数相加。见下例。 //例4.1 通过函数来实现复数相加。 #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 选择题 1.在下列运算符中,能重载的是( )。 (a) ! (b) sizeof (c) new (d) delete 2.在下列运算符中,不能重载的是( )。 (a) <= (b) >> (c) ::(d) &= 3.下列关于运算符重载的描述中,( )是正确的。 (a) 可以改变参与运算的操作数个数(b) 可以改变运算符原来的优先级 (c) 可以改变运算符原来的结合性(d) 不能改变原运算符的语义 4.下列函数中,能重载运算符的函数是( )。 (a) 成员函数(b) 构造函数(c) 析构函数(d) 友员函数 5.不能用友员函数重载的是( )。 (a) = (b) = = (c) += (d) != 6.下面描述中,错误的是( )。 (a) 只有系统预先定义的运算符才可能被重载 (b) 使用类型转换函数不能把一个类转换为另一个类 (c) 使用类型转换函数可以把类转换为基本类型 (d) 类型转换函数只能定义为一个类的成员函数,不能定义为类的友员函数 1、a,c,d 2、c 3、d 4、b,c 5、a 6、b 阅读下列程序,写出执行结果 1.#include〈iostream.h〉 class T { public : T( ) { a = 0; b = 0; c = 0; } T( int i , int j , int k ) { a = i; b =j ; c = k; } void get( int &i , int &j , int &k ) { i = a; j = b; k = c; } T operator * ( T obj ); private: int a , b , c; }; T T::operator * ( T obj ) { T tempobj; tempobj.a = a * obj.a; tempobj.b = b * obj.b; tempobj.c = c * obj.c; return tempobj; } void main( ) { T obj1( 1,2,3 ), obj2( 5,5,5 ), obj3; int a , b , c; 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++运算符重载总结 目录1.一般运算符重载2.关系运算符重载3.逻辑运算符重载4.单目运算符重载5.自增减运算符重载6.位运算符重载7.赋值运算符重载8.内存运算符重载9.特殊运算符重载10.总结c++的一大特性就是重载(overload),通过重载可以把功能相似的几个函数合为一个,使得程序更加简洁、高效。在c++中不止函数可以重载,运算符也可以重载。由于一般数据类型间的运算符没有重载的必要,所以运算符重载主要是面向对象之间的。 1.一般运算符重载 在进行对象之间的运算时,程序会调用与运算符相对应的函数进行处理,所以运算符重载有两种方式:成员函数和友元函数。成员函数的形式比较简单,就是在类里面定义了一个与操作符相关的函数。友元函数因为没有this指针,所以形参会多一个。 class A{public: A(int d):data(d){} A operator+(A&);//成员函数A operator-(A&); A operator*(A&); A operator/(A&); A operator%(A&); friend A operator+(A&,A&);//友元函数friend A operator-(A&,A&); friend A operator*(A&,A&); friend A operator/(A&,A&); friend A operator%(A&,A&);private: int data;};//成员函数的形式A A::operator+(A &a){ return A(data+a.data);}A A::operator-(A &a){ return A(data-a.data);}A A::operator*(A &a){ return A(data*a.data);}A A::operator/(A &a){ return A(data/a.data);}A A::operator%(A &a){ return A(data%a.data);}//友元函数的形式A operator+(A &a1,A &a2){ return A(a1.data+a2.data);}A operator-(A &a1,A &a2){ return A(a1.data-a2.data);}A operator*(A &a1,A &a2){ return A(a1.data*a2.data);}A operator/(A &a1,A &a2){ return A(a1.data/a2.data);}A operator%(A &a1,A &a2){ return A(a1.data%a2.data);}//然后我们就可以对类的对象进行+、-、*、/了。void main(void){ A a1(1),a2(2),a3(3); a1=a2+a3; //或者a1=a2.operator+(a3);} 注意:在进行a2+a3的时候会出错,因为我们在上面对+定义了两种方法,去掉一种即可。 2.关系运算符重载 因为函数体比较简单,后面我就只给出成员函数形式的函数声明了,关系运算符有==,!=,,=。 bool operator == (const A& ); bool operator != (const A& );bool operator bool operator bool operator > (const A& );bool operator >= (const A& ); 3.逻辑运算符重载 bool operator || (const A& );bool operator && (const A& );bool operator ! (); 第八章操作符重载 重载是C++多态性的体现之一。当定义新的数据类型之后,C++原有操作符提供的操作 在语义往往不能满足对新的数据类型的对象进行操作,因此必须对C++原有操作符的操作语 义进行扩充,这就是重载的应用需求背景。 8.1操作符重载概述 当在同一作用域内声明两个或多个相同的名字(即标识符)时,称该名字被重载。在同一作用域内的两个声明,如果声明的名字相同但是数据类型不同,则称这两个声明为重载声明。C++规定,只有函数声明可以被重载,对象声明或类型声明不允许重载。换言之, C++的这一规定将重载严格限制在函数范畴。 当重载的函数被调用时,从诸个可调用的重载函数( viable fu nctio ns )中究竟调用 那一个函数则由调用时实参的类型与函数声明时形参的类型相比较结果的一致性决定。这个选择与决定的过程称为重载解析。在C++中,根据函数的定义者是谁可以将函数分为两类。 一类是由程序员定义的函数,它们往往被称为用户自定义函数,另一类则是系统提供的函 数。就系统提供的函数而言,根据它们的调用方式,又可以进一步分为两类。一类是与用 户自定义函数调用方式相同的系统函数,它们往往称为库函数或类库中的成员函数;另一 类则沿用自然语言和数学语言的使用习惯,在各类表达式中完成相应的运算,它们往往称为操作符或运算符,但实际上是系统的预定义函数或操作符函数。例如对整型对象x、y,x+y 实际表示对预定义函数’+'的调用。x和y是预定义函数’+'的参数,但一般习惯上称为 ‘ + '的左操作数和右操作数。由于操作符实际上也是函数,不同的只在于操作符是系统的 预定义函数,因此操作符和用户自定义函数一样也可以重载。 以加法操作‘ +'为例,C++提供的‘ +'操作如果不考虑类库支持,则只能进行整数或实数的加法运算,若考虑类库支持则能够进行一般复数的运算。如果用复数来表示电路中的电流和电压,根据电路理论,只有电流和电流才能进行相加减的运算;同理,只有电压 和电压才能进行相加减的运算。因此,为了将复数用于电路计算,可以象下面的例子那样 设计一个用于电路计算的复数类,并且对加法操作的语义进行扩充。例8-1设计一个能够用于电路计算的复数类,并重载加法操作。 #i nclude "iostream.h" struct complex { complex(double re=0.0,double im=0.0,char ch1='U'); complex operator+(complex & c);〃声明重载加法操作 void show(); private: double real,imag; char ch; }; complex::complex(double re,double im,char ch1 ) { real=re;imag=im;ch=ch1; cout<<"c on structor is called!"< 实验12 运算符重载(2) 牛旭艳智能二班 20110807201 一、实验目的 1、进一步理解运算符重载,运用成员函数和友元函数等方法实现运算符的重载。 二、实验内容 1、重载函数调用运算符(),将以下的二维数组的下标表示方法: chessBoard[row][column]改为常用的表示方法: chessBoard(row,column) 2、重载下标运算符使之返回集合中最大的元素、次最大的元素以及第三大的元素。 3、开发多项式类Polynomial,多项式的每一项用数组表示,每项包含一个系数和一个指数。例如:2x4的指数为4,系数为2。 请开发一个完整的Polynomial类,包括构造函数、析构函数以及"get"函数和"set"函数。该类还要提供下述重载的运算符(分别使用成员函数和友元函数): 1)重载加法运算符+,将两个多项式相加; 2)重载减法运算符-,将两个多项式相减; 3)重载赋值运算符=,将一个多项式赋给另外一个多项式; 4)重载乘法算符*,将两个多项式相乘; 5)重载加法赋值运算符+=、减法赋值运算符-=以及乘法赋值运算符*=。 4.设计一个日期类Date,,要求: (1)包含年(year)、月(month)和日(day)私有数据成员。 (2)包含构造函数,重载关于一日期加上天数的加法运算符+、重载关于一日期减去天数的减加运算符-、重载输出运算符<<与输入运算符>>等。 提示:由于各C++编译器对于重载输入/出运算符为友元的兼容性都存在问题,最好重载输入/出运算符不声明为成员函数与友元函数,而声明一般函数,为编程更方便,可增加一些成员函数,比如: void SetYear(int y); // 设置年 int SetMonth(int m); // 设置月 int SetDay(int d); // 设置日 int GetYear() const; // 返回年 int GetMonth() const; // 返回月 int GetDay() const; // 返回日 static int IsLeapyear(int y); // 判断年份y是否为润年 static int GetDays(int y); // 年份y的天数 static int GetDays(const Date &d); // 日期d当前月份的天数 static int DateToNum(const Date &d); // 返回从公元1年1月1日起的天数 static Date NumToDate(int n); //由从公元1年1月1日起的天数返回日期 润年条件:年份能被4整除,并且年份不能被100整除,或者年份能被400整除 润年天数:366 平年天数:365运算符重载基础概念练习题
c 运算符的重载习题答案
C中用运算符重载实现矩阵运算
第十章 运算符重载 复习题
运算符重载题目
运算符重载练习题
第7章 运算符重载-习题
C++运算符重载
运算符重载
C++运算符重载讲解与经典实例 (2)
第11章 运算符重载 习题解答
C++实验21 运算符重载
C++程序设计运算符重载习题
运算符重载
c 运算符重载总结
第8章运算符重载
实验12 运算符重载