[苏州大学C++] 大一下C++第二次考试

题目如下:
请按要求编写一个类Circle,用于描述一个圆形,并用给定的main函数测试Circle类的功能。Circle类的要求如下:

  1. 包含圆形编号、圆心x坐标、圆心y坐标和半径等数据成员。圆形编号为整形。生成第1个圆形对象时编号为1,生成第2个圆形对象时编号为2,以此类推。每构造一个新的圆形,对象编号为当前最大编号加1(如当前最大编号为5,则生成的这个新圆形的编号应该为6)。
  2. 是否需要其它数据成员,可视情况自行决定。提示:建议使用两个静态变量。一个静态变量用于记录当前圆形对象的个数,此变量的值可增大或减小;另一个静态变量用于记录已经生成的圆形对象的最大编号,此变量的值只会增大不会减小。
  3. 1个带有3个参数的构造函数。3个参数分别初始化圆形的圆心x坐标、圆心y坐标和半径等数据成员。提示:圆形对象的编号也需要初始化。
  4. 1个拷贝构造函数。提示:圆形对象的编号不能简单复制。
  5. 1个获取当前圆形对象数量的函数。提示:此函数建议为静态函数。
  6. 前自增运算符,对半径自增1。
  7. 后自增运算符,对半径自增1。
  8. +运算符,用于将两个圆形加在一起,得到一个新的圆形。新圆形的圆心坐标是两个圆形坐标连线的中点,面积是两个圆形面积的和。提示:需要根据面积反算半径。
  9. 流输出运算,用于显示圆形的编号、圆心x坐标、圆心y坐标和半径、面积、周长。一个圆形的信息占1行。
  10. 析构函数。圆形对象销毁时,需要将当前圆形对象的数量减去1。
  11. 使用给定的main函数测试Circle类的功能。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
///#Author:Rye
#include<bits/stdc++.h>
#define PI 3.1415
using namespace std;

class Circle
{
private:
static int m_number;//当前圆对象的数量
static int m_maxCount;//最大编号

int m_count = 0;//对象编号
double m_x;
double m_y;
double m_r;
public:
Circle(double x,double y,double r){
m_x = x;
m_y = y;
m_r = r;
m_count = ++m_maxCount;
// cout<<"调用了构造函数"<<endl;
m_number++;
}
Circle(const Circle&C){
m_x = C.m_x;
m_y = C.m_y;
m_r = C.m_r;
m_count = ++m_maxCount;
// cout<<"调用了拷贝构造函数"<<C.m_count<<endl;
// m_maxCount++;
m_number++;

}
~Circle(){
// cout<<"调用了析构函数"<<endl;
m_number--;
}
static int get_num(){
return m_number;
}
Circle& operator++(){
m_r++;
// cout<<"前置++"<<endl;
return *this;
}//前置++
Circle operator++(int){
// cout<<"后置++"<<endl;
Circle temp(*this);//调用拷贝构造函数
temp.m_count = m_count;
m_r++;
return temp;
}//后置++
friend Circle operator+(const Circle &a,const Circle &b);
friend ostream &operator<<(ostream &out,const Circle &t);//流输出
};

//Circle& operator++(Circle &t){///友元函数重载
// t.m_r++;
// return t;
//}

//Circle operator++(Circle &t,int){
// Circle temp(t);//调用拷贝构造函数
// temp.m_count = t.m_count;
// Circle::m_maxCount--;
// Circle::m_number--;
// t.m_r++;
// return temp;
//}

Circle operator+(const Circle &a,const Circle &b){
double S = PI * (a.m_r * a.m_r + b.m_r * b.m_r);
double R = pow(S / PI, 0.5);
Circle NEW(a.m_x + b.m_x, a.m_y + b.m_y, R);
return NEW;
}

ostream &operator<<(ostream &out,const Circle &t){
cout << "圆的编号" << t.m_count << " x:" << t.m_x << " y:" << t.m_y << " 周长:" << 2 * PI * t.m_r << " 面积:" << PI * t.m_r * t.m_r << endl;
return out;
}

int Circle::m_maxCount = 0;
int Circle::m_number = 0;

int main()
{
Circle c1( 1.12, 2.23, 3.34 ), c2( c1 );

cout << c1 << c2;
cout << "Number of circles = " << Circle::get_num() << endl;

Circle c3 = c1 + c2;
cout << c3;
cout << "Number of circles = " << Circle::get_num() << endl;

cout << c1++;
cout << ++c2;
cout << c1++;

return 0;
}

其实很简单。
但是踩了一个坑,今天有同学来问我这道题,有关于静态变量。它的序号莫名其妙增加了。
我第一次写的时候也出现了这个问题,后来找到问题所在。
如果使用友元函数重载运算符,传入的参数没有使用常引用的时候,就会调用拷贝构造函数。
比如你把friend ostream &operator<<(ostream &out,const Circle &t);写成了friend ostream &operator<<(ostream &out,Circle t);
调用拷贝构造函数
那么cout << c1 << c2 就会调用2次拷贝构造函数和2次析构函数。在不涉及静态变量的时候,常引用和不写引用的方式是没有区别的。但是这道题目中,调用拷贝构造函数会使最大序号增加,而析构函数不会使最大序号减小,所以这种写法就错了。

常引用能够提高程序运行的效率,也能保护传递给函数的数据不被改变。引用型参数如果可以被定义为const,应该尽量定义为const。

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2024 Rye
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信