一、判断题
1、多数运算符可以重载,个别运算符不能重载,运算符重载是通过函数定义实现的。
T F
解析:T。运算符重载确实是通过函数定义来实现的。我们可以通过重载运算符定义自定义类型的对象在使用类似于内置数据类型的运算符时的行为。大多数运算符确实都可以被重载,而有少部分运算符不能被修改功能。
2、对每个可重载的运算符来讲,它既可以重载为友元函数,又可以重载为成员函数,还可以重载为非成员函数。
T F
解析:F。并不是每一个函数都可以被重载为所有三种类型的运算符重载(成员函数、非成员函数、友元函数)。不同的运算符具有不同的重载要求和限制,而且有些运算符只能以某种方式进行重载。
3、对单目运算符重载为友元函数时,可以说明一个形参。而重载为成员函数时,不能显式说明形参。
T F
解析:T。在我们将单目运算符重载为友元函数时,可以显式指定一个参数。这个参数表示被操作的对象。这使得友元函数能够访问类的私有成员,因此不需要将运算符函数定义为成员函数。而我们若是将单目运算符重载为成员函数时,它将在类的内部进行定义。在成员函数中,不需要显式地指定形参,因为成员函数默认可以访问类的成员。
4、重载运算符可以保持原运算符的优先级和结合性不变。
T F
解析:T。这是因为运算符重载只是改变了运算符操作数的行为,而不会影响运算符的语法规则、优先级或结合性。
5、预定义的提取符和插入符是可以重载的。
T F
解析:T。预定义的输入运算符(提取符 >>
)和输出运算符(插入符 <<
)是可以通过运算符重载进行自定义的。我们可以为自定义的类类型定义如何从流中提取数据以及如何将数据插入到流中。
6、重载operator+时,返回值的类型应当与形参类型一致。
比如以下程序中,operator+的返回值类型有错:
class A {
int x;
public:
A(int t=0):x(t){ }
int operator+(const A& a1){ return x+a1.x; }
};
T F
解析:F。运算符重载 operator+
的返回值类型并没有错误。实际上,代码在这里使用了不同的返回值类型,即 int
,而不是 A
类型,因为 operator+
返回一个整数结果,表示两个 A
对象的 x
成员之和。
7、重载关系运算符一般都返回true或false值。
T F
解析:T。关系运算符重载通常会返回布尔值,即 true
或 false
,用于比较两个对象的关系,例如相等性、不等性、大于、小于等。
8、The operator ::
can not be overloaded.
T F
解析:T。“::”运算符是作用域解析运算符,用于访问命名空间、类、结构体、枚举等作用域中的成员。由于它是用于标识作用域和命名空间的,不能被重载。这个运算符不允许用户自定义其行为,它在语言中有固定的含义和用途。
9、若重载为友元函数,函数定义格式如下:
<类型>operator<运算符>(<参数列表>)
{
<函数体>
}
T F
解析:F。未写明friend则不会将其重载为友元函数。
二、单选题
1、下列运算符中,( )运算符不能重载。
A.&& B.[ ] C.:: D.<<
解析:C。“::”运算符是作用域解析运算符,用于访问命名空间、类、结构体、枚举等作用域中的成员。由于它是用于标识作用域和命名空间的,不能被重载。这个运算符不允许用户自定义其行为,它在语言中有固定的含义和用途。
2、下列关于运算符重载的描述中,( )是正确的。
A.运算符重载可以改变操作数的个数
B.运算符重载可以改变优先级
C.运算符重载可以改变结合性
D.运算符重载不可以改变语法结构
解析:D。运算符重载允许对操作数的行为加以改变,但不会改变运算符的优先级、结合性或语法结构。重载运算符的目的是让自定义类型的对象在使用运算符时表现得像内置类型,从而提供直观和一致的操作体验。运算符的优先级、结合性和语法结构是由C++语言规范定义的,无法通过运算符重载来修改。
3、为了能出现在赋值表达式的左右两边,重载的"[]"运算符应定义为:
A.A operator [ ] (int);
B.A& operator [ ] (int);
C.const A operator [ ] (int);
D.以上答案都不对
解析:B。重载的"[]"运算符用于访问类似数组的元素,通常应返回一个引用(reference)类型,以允许在表达式中修改元素的值。所以正确的选项是 B,它定义了一个返回引用的运算符重载函数,允许修改通过 "[]" 访问的元素。
4、在C++中不能重载的运算符是
A.?: B.+ C.- D.<=
解析:A。不能重载三元条件运算符 ?:
。其他运算符如 +
、-
以及 <=
都是可以被重载的。
5、下列关于运算符重载的表述中,正确的是()。
A.C++已有的任何运算符都可以重载
B.运算符函数的返回类型不能声明为基本数据类型
C.在类型转换符函数的定义中不需要声明返回类型
D.可以通过运算符重载来创建C++中原来没有的运算符
解析:C。不是所有运算符都可以重载,比如 ::
和 .
等不能被重载;同时,运算符函数的返回类型可以声明为基本数据类型。而运算符重载可以为现有的运算符赋予自定义类类型的含义,但不能创建全新的运算符。故A、B、D均为错误。而类型转换运算符函数在定义时不需要显式声明返回类型,编译器会根据函数体中的返回语句自动推断返回类型,故选C。
6、能用友元函数重载的运算符是()。
A.+ B.= C.[] D.->
解析:A。友元函数可以用于重载部分运算符,但不是所有运算符都可以这样做。运算符 +
可以使用友元函数进行重载,因为它涉及到两个操作数之间的操作,而不涉及对象内部的成员。运算符 =
、[]
和 ->
不能使用友元函数进行重载。其中,=
运算符的重载是通过成员函数进行的,[]
运算符用于访问数组或类似数组的元素,->
运算符用于成员指针的访问。
7、下列哪一项说法是不正确的?
A.运算符重载的实质是函数重载
B.运算符重载可以重载为普通函数,也成员可以重载为成员函数
C.运算符被多次重载时,根据实参的类型决定调用哪个运算符重载函数
D.运算符被多次重载时,根据函数类型决定调用哪个重载函数
解析:D。运算符重载的解析是根据操作数的类型和参数来决定调用哪个运算符重载函数,而不是函数的类型。在运算符重载中,编译器会尝试根据操作数的类型找到最匹配的重载函数。这是根据实际参数类型的重载解析,而不是函数类型。
8、如何区分自增运算符重载的前置形式和后置形式?
A.重载时,前置形式的函数名是++operator,后置形式的函数名是operator ++
B.后置形式比前置形式多一个 int 类型的参数
C.无法区分,使用时不管前置形式还是后置形式,都调用相同的重载函数
D.前置形式比后置形式多一个 int 类型的参数
解析:B。当重载自增运算符时,前置形式和后置形式的区别在于参数列表。前置自增运算符重载没有参数,而后置自增运算符重载有一个额外的 int
参数,用于区分前置和后置形式。
9、下列关于运算符重载的描述正确的是( )。
A.运算符重载可以改变操作数的个数
B.可以创造新的运算符
C.运算符可以重载为友元函数
D.任意运算符都可以重载
解析:C。运算符重载不能改变操作数的个数,也不能创造全新的运算符,只能重新定义运算符的作用对象和行为。运算符可以重载为友元函数,但不是任意运算符都可以被重载。
10、在重载一个运算符时,如果其参数表中有一个参数,则说明该运算符是( )。
A.一元成员运算符
B.二元成员运算符
C.一元友元运算符
D.二元成员运算符或一元友元运算符
解析:D。对于二元成员运算符,参数表中只有一个参数,因为第二个操作数通过隐式的 this
指针传递;而对于一元友元运算符,参数表中也只有一个参数。
11、下列关于运算符重载的描述中,错误的是()。
A.运算符重载不改变优先级
B.运算符重载后,原来运算符操作不可再用
C.运算符重载不改变结合性
D.运算符重载函数的参数个数与重载方式有关
解析:B。运算符重载后,原来运算符的操作仍然可以用,但是根据所定义的运算符重载函数,运算符可能会以不同的方式执行操作。重载运算符并不会使原来的运算符操作不再可用,而是为定义的类型赋予了新的运算语义。
12、若需要为xv类重载乘法运算符,运算结果为xv类型,在将其声明为类的成员函数时,下列原型声明正确的是_________。
A.xv*(xv); B.operator*(xv); C.xv operator*(xv); D.xv operator*(xv,xv);
解析:C。当将乘法运算符重载为类的成员函数时,参数列表中应只有一个参数,表示右操作数。因此,正确的原型声明应该是 xv operator*(xv);
,这样可以使左操作数为调用乘法运算符的对象,右操作数通过函数参数传递。
13、下列运算符中,不可以重载的是( )
A.new B.++ C..* D.[]
解析:C。.*(成员指针运算符)是不能被重载的。这是因为 .* 用于访问类的成员指针,而成员指针运算符是无法通过运算符重载来改变其行为的。
三、函数题
1、Point类的运算
定义Point类,有坐标x,y两个私有成员变量;对Point类重载“+”(相加)、“-”(相减)和“==”(相等)运算符,实现对坐标的改变,要求用友元函数和成员函数两种方法实现。对Point类重载<<运算符,以使得代码 Point p; cout<<p<<endl;可以输出该点对象的坐标。
函数接口定义:
实现Point类。
裁判测试程序样例:
/* 请在这里填写答案 */
int main(int argc, char const *argv[])
{
Point p1(2,3);
cout<<p1<<endl;
Point p2(4,5);
cout<<p2<<endl;
Point p3 = p1+p2;
cout<<p3<<endl;
p3 = p2-p1;
cout<<p3<<endl;
p1 += p2;
cout<<p1<<endl;
cout<<(p1==p2)<<endl;
return 0;
}
输入样例:
无
输出样例:
在这里给出相应的输出。例如:
2,3
4,5
6,8
2,2
6,8
0
代码解答:
#include<iostream>
using namespace std;
class Point
{
friend ostream &operator<<(ostream &cout, Point &p);
friend Point operator+ (Point &p1, Point &p2);
friend Point operator- (Point &p1, Point &p2);
friend Point operator+= (Point &p1,Point &p2);
friend bool operator==(Point &p1,Point &p2);
public:
Point(int a=0, int b=0):x(a),y(b){}
private:
int x;
int y;
};
Point operator+ (Point &p1, Point &p2)
{
Point temp;
temp.x = p1.x + p2.x;
temp.y = p1.y + p2.y;
return temp;
}
Point operator- (Point &p1, Point &p2)
{
Point temp;
temp.x = p1.x - p2.x;
temp.y = p1.y - p2.y;
return temp;
}
Point operator+= (Point &p1,Point &p2)
{
p1.x += p2.x;
p1.y += p2.y;
return p1;
}
bool operator==(Point &p1,Point &p2)
{
if(p1.x==p2.x&&p1.y==p2.y)
{
return true;
}
else
{
return false;
}
}
ostream &operator<<(ostream &cout, Point &p)
{
cout<<p.x<<","<<p.y;
return cout;
}
2、复数的加减运算(运算符重载)
###复数加减(运算符重载)
- 声明一个复数类CComplex(类私有数据成员为double型的real和image)
- 定义构造函数,用于指定复数的实部与虚部。
- 重载<<运算符,以格式real+image i的格式输出当前对象(当虚部为非负数时,实部虚部中间用+号连接,当虚部为负数时,实部虚部用-号连接:如3+4i,3-4i,3+0i)。
- 重载+运算符,实现两个复数对象之和(实部虚部分别相加)。
- 重载-运算符,实现两个复数对象的差(实部虚部分别相减)。
输入格式:
输入有两行:
第一行是复数c1的实部与虚部,以空格分隔;
第二行是复数c2的实部与虚部,以空格分隔。
输出格式:
输出共四行:
第一行是c1;
第二行是c2;
第三行是c1与c2之和;
第四行是c1与c2之差;
函数接口定义:
在这里描述类定义
class CComplex{...}
裁判测试程序样例:
#include <iostream>
using namespace std;
/* 请在这里填写答案 */
int main() {
double r1,r2,i1,i2;
cin>>r1>>i1;
cin>>r2>>i2;
CComplex c1(r1,i1),c2(r2,i2),c3,c4;
cout<<c1;
cout<<c2;
c3=c1+c2;
cout<<c3;
c4=c1-c2;
cout<<c4;
return 0;
}
输入样例:
10 20
30 40
输出样例:
10+20i
30+40i
40+60i
-20-20i
代码解答:
#include <iostream>
using namespace std;
class CComplex
{
public:
CComplex(){}
CComplex(double _r,double _i){
real=_r;
imag=_i;
}
friend ostream &operator >>(ostream & ,CComplex & );
CComplex operator+(CComplex c) {
return CComplex(real+c.real,imag+c.imag);
}
CComplex operator-(CComplex c){
return CComplex(real-c.real,imag-c.imag);
}
double real,imag;
};
ostream &operator <<(ostream & os ,CComplex& c ){
os<<c.real<<showpos<<c.imag<<"i"<<noshowpos<<endl;
return os;
}
3、大整数求和(运算符重载)
BigInt类表示不超过100位的无符号大整数。试重载>>,<<和+,以支持无符号大整数的输入、输出与求和(假设结果仍是一个不超过100位的无符号大整数)。
重载面向BigInt类对象的运算符:
>>
<<
+
裁判测试程序样例:
#include <iostream>
#include <string>
using namespace std;
/* 请在这里填写答案 */
int main(){
BigInt a, b, c;
cin>>a>>b;
c=a+b;
cout<<a<<"+"<<b<<"="<<c<<endl;
return 0;
}
输入样例:
123456789
987654321
输出样例:
123456789+987654321=1111111110
代码解答:
class BigInt
{
int *a;
int max; //数组长度
string num; //用于输入数字,转化为数组
public:
BigInt()
{
a = new int[101];
max=0;
}
void swap_string_to_dig()
{
int len = num.length();
max = len;
for(int i=len-1;i>=0;i--)
a[len-i-1] = num[i]-'0';
for(int i=len;i<101;i++)
a[i] = 0;
}
friend istream& operator>>(istream &is,BigInt &x)//输入
{//注意此处为友元类型---因为是cin>>形式调用,调用的对象是istream类型的,而不是BigInt类,下同
is>>x.num;
return is;
}
friend ostream& operator<<(ostream &os,BigInt &x)//输出
{
os<<x.num;
return os;
}
BigInt operator+(BigInt &x)
{
BigInt c;
int n,i=0,j=0,k=0;
x.swap_string_to_dig();
swap_string_to_dig();
int l=0;
while(j<max || k<x.max)
{
c.a[i] = a[j++] + x.a[k++] + l; //每次相加
l = c.a[i]/10;//将位数进位,由于a[i]最多为18,所以l最大为1,于是最多进1位
c.a[i]%=10;//保持数字在10以内
i++;
}
while(l>0)
{
c.a[i] += l; //l为进位数
l = c.a[i]/10;
c.a[i]%=10;
i++;
}
c.max = i;
//c.num的转化
for(i=c.max-1;i>=0;i--)
c.num += c.a[i]+'0';
return c;
}
};
四、编程题
1、分数加法运算重载
相信同学们对复数运算符重载已经相当熟悉啦,那今天那我们来看看分数又该如何处理呢?定义一个分数类FS,有私有成员分子fz,分母fm。另有公有成员函数FS operator + (const FS &f)对运算符“+”进行重载,实现两个分数相加。题目首先给出一个整型数n,紧跟着2n行输入,输入形如3z4m,代表分子为3,分母为4。其中分母不为0,输入时分母可以为负数,但输出时分母必须为正数。
要求对分数进行两两求和,并化简。(备注说明:分数为0时,表示成0z1m,如果结果为负数,那么分子取负数,分母为正数)
示例如下:
输入:
3
4z9m
2z9m
4z5m
5z4m
2z-5m
1z-5m
输出:
2z3m
41z20m
-3z5m
代码解答:
#include<iostream>
using namespace std;
class FS
{
private:
int fz;
int fm;
public:
FS()
{
fm=1;
fz=0;
}
void set(int m,int z)
{
fm=m;
fz=z;
}
void del()
{
fm=1;
fz=0;
}
FS operator + (const FS &f);
int huajian(int,int);
void display();
} ;
FS FS::operator +(const FS &f)
{
FS f1;
f1=f;
f1.fz=fz*f1.fm+f1.fz*fm;
f1.fm=fm*f1.fm;
return f1;
}
int FS::huajian(int Fenz,int Fenm)
{
while(Fenm!=0)
{
int temp=Fenz%Fenm;
Fenz=Fenm;
Fenm=temp;
}
return Fenz;
}
void FS::display()
{
if(fz==0)
{
cout<<"0z1m"<<endl;
}
else
{
int l=huajian(fz,fm);
fz=fz/l;
fm=fm/l;
if(fm<0)
{
fm=-1*fm;
fz=-1*fz;
}
if(fz%fm!=0)
{
cout<<fz<<"z"<<fm<<"m"<<endl;
}
if(fz%fm==0)
{
cout<<fz<<"z"<<"1m"<<endl;
}
}
}
int main()
{
FS fs;
FS fens[100];
string a[100];
int n;
cin>>n;
int l,k;
for(int i=0; i<2*n; i++)
{
cin>>a[i];
int fm=0,fz=0;
int o=0;
int u=0;
for(int j=0; j<a[i].size(); j++)
{
if(a[i][0]=='-')
{
o=1;
}
if(a[i][j]=='z')
{
l=j;
if(a[i][l+1]=='-')
{
u=1;
}
}
if(a[i][j]=='m')
{
k=j;
}
}
int count1=1,count2=1;
if(o==1)
{
for(int j=l-1; j>0; j--)
{
fz+=(a[i][j]-'0')*count1;
count1*=10;
}
fz=-1*fz;
}
else
{
for(int j=l-1; j>=0; j--)
{
fz+=(a[i][j]-'0')*count1;
count1*=10;
}
}
if(fz==0)
{
fens[i].set(0,0);
}
else
{
if(u==1)
{
for(int j=k-1; j>l+1; j--)
{
fm+=(a[i][j]-'0')*count2;
count2*=10;
}
fm=-1*fm;
}
else
{
for(int j=k-1; j>l; j--)
{
fm+=(a[i][j]-'0')*count2;
count2*=10;
}
}
fens[i].set(fm,fz);
}
fs=fs+fens[i];
if((i+1)%2==0)
{
fs.display();
fs.del();
}
}
return 0;
}
2、复数的比较
题目描述:建立一个复数类,实数和虚数是其私有数据成员。建立一个>(大于号)的运算符重载,比较两个复数间模的大小。
输入格式:测试输入包含若干测试用例,每个测试用例占一行。每个测试用例包括四个数字,前两个数字分别表示第一个复数的实部和虚部,第三个和第四个数字分别表示第二个复数的实部和虚部。每个数字之间用空格间隔。当读入一个测试用例是0 0 0 0时输入结束,相应的结果不要输出。
输出格式:对每个测试用例输出一行。当第一个复数的模大于第二个复数的模时,输出 true ,当第一个复数的模小于或等于第二个复数的模时,输出false
输入样例:
3 5 4 0
0 3 4 1
0 0 0 0
输出样例:
true
false
代码解答:
#include<iostream>
#include<math.h>
using namespace std;
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0, double i = 0) {
real = r;
imag = i;
}
double modulus() {
double modulus;
modulus = sqrt(real *real + imag * imag);
return modulus;
}
bool friend operator>( Complex o,Complex p) {
double a = o.modulus();
double b = p.modulus();
if (a > b) {
return true;
}
else if (a <=b) {
return false;
}
}
};
int main() {
double a, b, c, d;
while(cin >> a >> b >> c >> d) {
if (a == 0 && b == 0 && c == 0 && d == 0)
break;
Complex p1(a, b);
Complex p2(c, d);
if (p1 > p2) {
cout << "true" << endl;
}
else {
cout << "false" << endl;
}
}
return 0;
}