对象传递与静态成员

一、实验目的
O进一步加深对类和对象的理解;
O掌握几种对象传递的使用方法 ;
O掌握静态成员的概念和使用。
二、实验内容
PART A:了解三种不同的对象传递方式
(1)使用对象作为函数参数。
在向函数传递对象时,是通过“传值调用”传递给函数的,即单向传递,只由实参传给形参,而不能由形参传回来给实参。因此函数中对对象的任何修改均不影响调用该函数的对象本身的值。
代码如下:

#include <iostream>
using namespace std;
class Tr {
public:
	Tr(int n)
	{
		i = n;
	}
	void set_i(int n)
	{
		i = n;
	}
	int get_i()
	{
		return i;
	}
private:
	int i;
};
void sqr_it(Tr ob)
{
	ob.set_i(ob.get_i() * ob.get_i());
	cout << "在函数sqr_it内,形参对象ob的数据成员i的值为:" << ob.get_i();
	cout << endl;

}
int main()
{
	Tr obj(10);
	cout << "调用函数sqr_it前,实参对象obj的数据成员i的值为:";
	cout << obj.get_i() << endl;
	sqr_it(obj);
	cout << "调用函数sqr_it后,实参对象obj的数据成员i的值为:";
	cout << obj.get_i() << endl;
	return 0;
}

运行结果:在这里插入图片描述
运行结果分析:
调用函数前实参对象 obj.i 的值是 10,对象在函数中值被修改为100,对象最终输出值还是其本身为10。从运行结果可以看出,在函数中对对象的任何修改均不影响调用该函数的对象本身。
(2)使用对象指针作为函数参数。
使用对象指针作为函数参数是实现“传址调用”,即在函数调用时使实参对象和形参对象指针变量指向同一内存地址,在函数调用过程中,对形参对象指针所指对象值的改变也同样影响着实参对象的值。
代码如下:

#include <iostream>
using namespace std;
class Tr {
public:
	Tr(int n)
	{
		i = n;
	}
	void set_i(int n)
	{
		i = n;
	}
	int get_i()
	{
		return i;
	}
private:
	int i;
};
void sqr_it(Tr* ob)//对象指针ob作为函数sqr_it的形参
{
	ob->set_i(ob->get_i() * ob->get_i());
	cout << "在函数sqr_it内,形参对象ob的数据成员i的值为:" << ob->get_i();
	cout << endl;

}
int main()
{
	Tr obj(10);
	cout << "调用函数sqr_it前,实参对象obj的数据成员i的值为:";
	cout << obj.get_i() << endl;
	sqr_it(&obj);
	cout << "调用函数sqr_it后,实参对象obj的数据成员i的值为:";
	cout << obj.get_i() << endl;
	return 0;
}

运行结果:在这里插入图片描述
运行结果分析:
调用函数前实参对象 obj.i 的值是 10,函数调用中形参对象 ob.i 的值修改为100 ,函数调用后实参对象 obj.i 的值也变为 100。从运行结果可以看出,形参对象指针所指对象的值的改变也同样影响着实参对象的值。
(3)使用对象引用作为函数参数
使用对象引用作为函数参数不但具有对象指针用作函数参数的特点,而且用对象引用作函数参数将更简单、更直接。
代码如下:

#include <iostream>
using namespace std;
class Tr {
public:
	Tr(int n)
	{
		i = n;
	}
	void set_i(int n)
	{
		i = n;
	}
	int get_i()
	{
		return i;
	}
private:
	int i;
};
void sqr_it(Tr&ob)
{
	ob.set_i(ob.get_i() * ob.get_i());
	cout << "在函数sqr_it内,形参对象ob的数据成员i的值为:" << ob.get_i();
	cout << endl;

}
int main()
{
	Tr obj(10);
	cout << "调用函数sqr_it前,实参对象obj的数据成员i的值为:";
	cout << obj.get_i() << endl;
	sqr_it(obj);
	cout << "调用函数sqr_it后,实参对象obj的数据成员i的值为:";
	cout << obj.get_i() << endl;
	return 0;
}

运行结果:在这里插入图片描述
运行结果分析:
调用函数前实参对象 obj.i 的值是 10,函数调用中形参对象 ob.i 的值修改为100 ,函数调用后实参对象 obj.i 的值也变为 100。传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象的操作。
PART B
O掌握静态成员的概念和使用
O由关键字static修饰说明的成员,称为静态成员(static class member) 。
O静态成员为所有对象共享,只有一份存于公用内存中。
O静态成员包括静态数据成员和静态函数成员。

在一个类中,将一个数据成员说明为 static,这种成员称为静态数据成员。与一般的数据成员不同,无论建立多少个类的对象,都只有一个静态数据成员的拷贝。从而实现了同一个类的不同对象之间的数据共享。
代码如下:

#include <iostream>
using namespace std;
class Ctest {
	static int count;//私有成员
public:
	Ctest()
	{
		++count;
		cout << "对象数量=" << count << '\n';
	}
};
int Ctest::count = 0;//对静态数据定义性说明
int main(void)
{
	Ctest a[3];
	return 0;
}

运行结果:
在这里插入图片描述
运行结果分析:
在上面的例子中,类 Ctest 的数据成员 count 被声明为静态的,它们为所有 Ctest类的对象所共享。因此,每调用一次构造函数,使数据成员count 加 1,调用结束后,它的值发生不会改变。
PART C
O创建一个TStudent类,完成以下功能:
O该类包括三个函数:InitStudent、ExpendMoney和ShowMoney;
O采用float m_ClassMoney变量作为静态变量,用于存储班级的班费,初始值设为1000;
OInitStudent (char name[])主要负责完成学生姓名的初始化;OExpendMoney(float money)主要完成班费的花销计算;oShowMoney()主要完成班费余额显示;
O主程序中分别定义A、B、C三个学生,每个学生为一个对象,每个学生分别消费班费50,98.5,500.53,最后显示班费的余额。

代码如下:

#include <iostream>
using namespace std;
class TStudent {
	static float m_ClassMoney;//私有成员
public:

	void InitStudent(const char* name)
	{
		cout << "学生姓名:" << name << endl;
	}
	void ExpendMoney(float money)
	{
		cout << "消费班费:" << money << endl;
		m_ClassMoney = m_ClassMoney - money;
	}
	void ShowMoney()
	{
		cout << "班费还剩余:" << m_ClassMoney << endl;
	}
private:
	int num;
};
float TStudent::m_ClassMoney = 1000;//对静态数据定义性说明

int main(void)
{
	TStudent a, b, c;
	a.InitStudent("小明");
	a.ExpendMoney(50);
	a.ShowMoney();
	b.InitStudent("小红");
	b.ExpendMoney(98.5);
	b.ShowMoney();
	c.InitStudent("小黑");
	c.ExpendMoney(500.53);
	c.ShowMoney();
	return 0;
}

运行结果:在这里插入图片描述

运行结果分析:
程序中采用float m_ClassMoney变量作为静态变量,它们为所有 TStudent类的对象所共享。因此,每次对m_ClassMoney 操作,其值都会在原有的基础上发生改变。所以能够达到随时记录班费的目的。
三、问题解决

运行错误型别:在这里插入图片描述
相应代码:

在这里插入图片描述

在这里插入图片描述
查阅资料后得知,使用Visual Studio 2019时经常会出现const char* 类型的实参与char* 类型的形参不兼容。对此可以有两种解决方法,放方法1为将结构体中定义的 char * 前面加上 "const"修饰,如下图,可以成功运行,得到正确结果。
在这里插入图片描述
方法二为 在Visual Studio 2019右侧栏创建的项目上右击“项目名称”——>“属性”——>“C/C++”——>“语言”,将“符合模式”改为“否”,也能够使结果正确。
此外还可以声明成
void InitStudent(string name)
{
cout << “学生姓名:” << name << endl;
}
这样就该类型问题就能够顺利解决。
四、实验总结
(1)在进行对象传递时,可以使用对象作为函数参数,使用对象指针作为函数参数,使用对象引用作为函数参数,这三种方法,它们各有不同的特点。其中,使用对象作为函数参数时,对象的值在调用函数后不改变,使用对象指针和对象引用作为函数参数时,可以修改对象本身的值,使用时可根据不同的程序功能来选用。
(2)在一个类中,将一个数据成员说明为 static,这种成员称为静态数据成员。无论建立多少个类的对象,都只有一个静态数据成员的拷贝。从而实现了同一个类的不同对象之间的数据共享。每次对对象变量 操作,其值都会在原有的基础上发生改变。所以能够达到跟随性的目的。
(3)当程序运行出错后,可采用多种方法进行修改,使用时,明白其错误原因,应用最合适的方法。
参考链接: https://blog.csdn.net/qq_42955211/article/details/113748774

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值