c++程序设计课后习题6-20

本文详细描述了一个名为SimpleCircle的圆类,涉及构造函数、内存管理、面积和周长计算。着重讲解了如何避免使用局部变量导致的内存问题,并提供了change_itsradius函数两种正确写法的对比。
摘要由CSDN通过智能技术生成

【题目】实现一个名为SimpleCircle的简单圆类。其数据成员int* itsRadius为一个指向其半径值的指针,存放其半径值。设计对数据成员的各种操作,给出这个类的完整实现并测试这个类。

 根据题意,可以有以下几个功能:①根据半径计算面积、周长;②对半径进行运算等等。

<使用平台:Microsoft visual studio>

代码如下:

#include<iostream>
#include<cmath>
using namespace std;

const double PI = 3.1415;

class SimpleCircle
{
public:
	SimpleCircle(int* itsradius):itsRadius(itsradius)   //构造函数
	{
		cout << "Constructor called." << endl;
	}
	SimpleCircle()  //无参默认构造函数
	{
		itsRadius = new int();   //注释①
		cout << "Default Constructor called." << endl;
	}
	SimpleCircle(SimpleCircle& circle)  //拷贝构造函数,用来初始化另外的对象
	{
		itsRadius = new int(*circle.itsRadius);  //此处同上注释①
		cout << "Calling the constructor..." << endl;
	}
	~SimpleCircle()
	{
		cout << "Destructor called." << endl;
	}
	void get_itsradius();  //显示出圆的半径
	void get_itsarea();  //计算出圆的面积
	void get_itscircle();  //计算出圆的周长
	void change_itsradius(int num);  //改变圆的半径到某个值
	void add_itsradius();  //给圆的半径增加值
private:
	int* itsRadius;
};

void SimpleCircle::get_itsradius()  //显示出圆的半径
{
	cout << endl << "the radius now is: " << *itsRadius << endl;
}
void SimpleCircle::get_itsarea()  //计算出圆的面积
{
	cout << "the area is: " << 2 * PI * pow(*itsRadius, 2) << endl;
}
void SimpleCircle::get_itscircle() //计算出圆的周长
{
	cout << "the circle is: " << 2 * PI * (*itsRadius) << endl;
}
void SimpleCircle::change_itsradius(int num)  //改变圆的半径到某个值
{
	*itsRadius = num;
	cout << endl << "After changing..." << endl << endl << "the radius now is: " << *itsRadius << endl;
	cout << "The change_itsradius has finished its function." << endl;
}
void SimpleCircle::add_itsradius()  //给圆的半径增加值
{
	string q;
	int n = 0;
	cout << endl << "now we are in the function add_itsradius——";
	cout << endl << "Do you want to add some numbers to the radius?" << endl << "yes or no:";
	cin >> q;
	while(q != "yes"&&q != "no")
	{
		cout << "Invalid inputs!! please enter again" << endl;
		cin >> q;
	}
	if (q == "yes")
	{
		cout << "please enter the numbers which will be added later:";
		cin >> n;
	}
	else if (q == "no")
	{
		cout << "The programe is over,thank you for testing." << endl;
	}

	cout << endl << "Congratulations! The final radius is: " << (*itsRadius)+n << endl;
}

int main()
{
	int r = 1;
	int* radius = &r;

	SimpleCircle mycircle1(radius);  //调用含参的构造函数
	mycircle1.get_itsradius();
	mycircle1.get_itsarea();
	mycircle1.get_itscircle();

	mycircle1.change_itsradius(5);  //调用change函数将radius改变到某个值再进行计算
	mycircle1.get_itsarea();
	mycircle1.get_itscircle();

	mycircle1.add_itsradius();  //调用add函数给radius加值再进行计算
	mycircle1.get_itsarea();
	mycircle1.get_itscircle();

	cout << endl << "****************TESTING****************" << endl;
	SimpleCircle mycircle2;  //调用无参默认构造函数
	mycircle2.get_itsradius();  //验证
	mycircle2.get_itsarea();
	mycircle2.get_itscircle();

	mycircle2.change_itsradius(3);
	mycircle2.get_itsradius();
	mycircle2.get_itsarea();
	mycircle2.get_itscircle();

	mycircle2.add_itsradius();

	SimpleCircle mycircle3(mycircle1);  //调用拷贝构造函数
	mycircle3.get_itsradius();  //验证
	mycircle3.get_itsarea();
	mycircle3.get_itscircle();

	return 0;
}

输出结果如下

  • 完整结果:

  •  对于add函数的不同情况:(此处省略默认构造函数和拷贝构造函数的测试结果)

【易错点】

 对于代码中注释①的解释:局部变量出了其作用域后内存单元就被系统回收,但是指针可以不正确访问,指向的为随机值。

//定义一个局部变量
SimpleCircle()  //无参默认构造函数
{
	int rr = 8;
    itsRadius = &rr;   //局部变量出了其作用域后内存单元就被系统回收。
	cout << "Default Constructor called." << endl;
}

//优化方案
SimpleCircle()  //无参默认构造函数
{
	itsRadius = new int();   //给其分配动态内存空间。
	cout << "Default Constructor called." << endl;
}

【注】

  • 其实如果采用上述定义一个局部变量的方法,数据成员int* itsRadius仍可以访问原先局部变量rr所在的位置,但是此时这个位置的内容已经被系统回收了,因此会由系统随机分配,从而出现随机值。类比于

c语言中free释放了一个结构体,但是它里面的指针却依然可以访问?https://zhidao.baidu.com/question/2144085304015597828.html?qbl=relate_question_2&word=%D6%B8%D5%EB%D6%B8%CF%F2%B5%C4%B1%E4%C1%BF%B1%BB%CF%FA%BB%D9%C1%CB%CE%AA%CA%B2%C3%B4%BB%B9%BF%C9%D2%D4%B7%C3%CE%CA

有趣的说法↑

因此优化前的写法运行后,change_itsradius函数在上述写法中可以运行成功(在这个函数里有对itsRadius的内容分配,另:解释在下文),而add_itsradius函数运行结果出现随机值(即上述【注】) 。

  • change_itsradius函数的写法问题
SimpleCircle()  //无参默认构造函数
{
	int rr = 8;
    itsRadius = &rr;   //局部变量出了其作用域后内存单元就被系统回收。
	cout << "Default Constructor called." << endl;
}

//改变圆的半径到某个值

/*写法①*/
void SimpleCircle::change_itsradius(int num)
{
	*itsRadius = num;
	cout << endl << "After changing..." << endl << endl << "the radius now is: " << *itsRadius << endl << endl;
}

/*写法②*/
void SimpleCircle::change_itsradius(int num) 
{
	itsRadius = &num;
	cout << endl << "After changing..." << endl << endl << "the radius now is: " << *itsRadius << endl << endl;
}

写法①:直接将num的值给了itsRadius指向的内容,相当于给itsRadius进行内容分配,因此出了change_itsradius函数之后,虽然num作为局部变量内存单元被回收,itsRadius指向的内容已经分配了num的值,因此在求面积和周长时可以正常使用;

写法②【不推荐书写】:itsRadius指向num,出了函数之后,num的内存单元被系统回收,(与上述【注】同理)指针可以<不正确>访问,指针指向的位置由系统随机分配,此时出现的就是随机值。{解决办法:分配动态内存空间}相比较而言,推荐写法①。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值