第3关:静态成员 —— 模拟共享书店错误

  • 任务要求
  • 参考答案
  • 评论2

任务描述

本关任务:假设有一个这样的共享书店,当客户进入书店时需要托管一定数量的书籍,而这些书籍将被书店内所有用户共享,当客户离开书店时,他便会把之前进入书店托管的书一起带走。现请你编写代码设计这个共享书店。

相关知识

对象的内存中包含了成员变量,不同的对象占用不同的内存,这使得不同对象的成员变量相互独立,它们的值不受其他对象的影响。例如有两个相同类型的对象 a、b,它们都有一个成员变量 name,那么修改 a 对象的 name 值不会影响 b 中的 name 值。

可是有时候我们希望在多个对象之间共享数据,即对象 a 改变了某份数据后对象 b 可以检测到。共享数据的典型使用场景是计数。在 C++ 中,我们可以使用静态成员变量来实现多个对象共享数据的目标。

下面我们就一起之来学习静态成员的声明、定义及使用。

静态成员

静态成员变量是一种特殊的成员变量,它用关键字 static 来修饰。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本,对它做出修改时所有对象都是可见的。

静态成员在类的所有对象中是共享的。声明一个静态成员与声明一个非静态成员(也叫实例成员)基本一致,只需要在声明的最前面加上一个 static 关键字即可。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。

例如:

 
  1. class Test
  2. {
  3. public:
  4. int A; // 实例成员
  5. static int B; // 静态成员变量
  6. static void Fun1(); // 静态成员函数
  7. };

注意:静态成员也是有访问性的。

定义分成两部分,一是静态变量的初始化,二是静态函数的定义

静态变量的初始化不能在类的定义中,但是可以在类的外部通过使用范围解析运算符::来重新声明静态变量从而对它进行初始化。而定义静态函数,那就与定义实例函数一样了。

例如:

 
  1. class Test
  2. {
  3. public:
  4. static string HelloStr;
  5. static void Hello();
  6. void World();
  7. };
  8. string Test::HelloStr = "Hello"; // 静态变量初始化
  9. void Test::World() // 定义实例成员函数
  10. {
  11. cout<<"World"<<endl;
  12. }
  13. void Test::Hello() // 定义静态函数,与定义 World 函数形式一样
  14. {
  15. cout<<"Hello"<<endl;
  16. }
访问静态成员

静态成员的访问有以下两种方法:

  1. 使用类型名::静态成员格式访问;

  2. 通过对象访问。

第一种访问方式可以将其看做是一个全局变量,只不过变量名要带上类型名::的前缀;第二种可以将其看做是对象中的一个实例成员。

例如:

 
  1. /* Test类的定义同上文 */
  2. int main()
  3. {
  4. cout << Test::HelloStr << endl; // 通过作用域运算符访问
  5. Test::HelloStr = "World"; // 修改静态变量 HelloStr
  6. Test t1;
  7. cout << t1.HelloStr <<endl; // 通过对象访问
  8. Test::Hello(); // 通过作用域运算符访问
  9. t1.World(); // 通过对象访问
  10. }

输出结果为:

 
  1. Hello
  2. World
  3. Hello
  4. World

注意第一、二行输出的差别,那是因为代码修改了所有对象共享的Test::HelloStr静态变量。

编程要求

在右侧编辑器中的Begin-End之间补充代码,设计一个 User 类(客户类),现有一个共享书店,该书店客户在进入书店时需要托管一定量的书籍,而这些书籍将由书店内所有用户共享,当客户离开书店时,他还是要将他进入书店时托管的书带走。设计时访问性可自主选择,具体要求如下:

  • 姓名:string Name

  • 托管的书籍量:int Books

  • 带参构造函数:User(string name,int books),使用这两个参数初始化内部的两个成员,同时按照姓名 数量 进入的格式打印一条消息。

  • 析构函数:~User(),按照姓名 数量 离开的格式打印一条消息。

  • 静态成员函数:void GetState(),按照书店人数:用户总数,书店共享书数量:书籍总数,人均共享数量:人均书籍量的格式打印一条消息,其中人均书籍量只保留整数部分,具体请参考测试说明。

提示:可以增加 UserCount ,BookCount 两个静态变量用于记录已有用户数和已有书籍数。

测试说明

平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:

测试输入:厉宏富 10 冷欣荣 2 叶文光 0

预期输出:

 
  1. 厉宏富 10 进入
  2. 冷欣荣 2 进入
  3. 书店人数:2,书店共享书数量:12,人均共享数量:6
  4. 厉宏富 10 离开
  5. 叶文光 0 进入
  6. 书店人数:2,书店共享书数量:2,人均共享数量:1
  7. 冷欣荣 2 离开
  8. 书店人数:1,书店共享书数量:0,人均共享数量:0
  9. 叶文光 0 离开

开始你的任务吧,祝你成功!

虽然能过,但有错误

代码如下

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

/********* Begin *********/
class User
{
	//在此处声明所需的成员
    public:
	static int UserCount;
	static int BookCount; 
    string Name;
    int Books;
    User(string name,int books);
    ~User();
   static void GetState();
};
int User::UserCount=0;
int User::BookCount=0;
User::User(string name,int books)
{
	UserCount++;
	
	Name=name;
	Books=books;
	cout<<Name<<" "<<Books<<" "<<"进入"<<endl; 
	BookCount+=Books;
}
User::~User()
{
	UserCount--;
	cout<<Name<<" "<<Books<<" "<<"离开"<<endl;
	BookCount-=Books;
}
void User::GetState()
{
cout<<"书店人数:"<<User::UserCount<<","<<"书店共享书数量:"<<User::BookCount<<","<<"人均共享数量:"<<User::BookCount/User::UserCount<<endl; 
}

/********* End *********/

他给的.cpp原文件中有错哟

代码如下

#include "usr.h"
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string name1,name2,name3;
	int a,b,c;
	cin >> name1 >> a >> name2 >> b >> name3 >> c ;
    User *u1 = new User(name1,a);
    User *u2 = new User(name2,b);
    User::GetState();
    delete u1;
    u1 = new User(name3,c);
    User::GetState();
    delete u2;
	User::GetState();
    delete u1;
    User::GetState();  //已经成废指针了,为啥还要调用?
}

  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值