任务描述
本关任务:仿真和游戏中经常有计算机生成的兵力,从诞生开始就有一定的自主行为。请为火星战士设计和定义类Martian,使得每产生一个对象,就会按规则判断等待还是进攻。具体要求如下:
Martian类的基本属性:
- string name; // 火星战士的名字
- int mCount; //当前系统中存活的火星战士总数(消亡时需要减掉)
- int id //火星战士的流水号(只加不减,保证是唯一的ID,不会与消亡的重号)
- int mid //火星战士的身份证号(每个火星战士的身份证号是唯一的)
Martian类的功能:
(1) 构造函数: 每构造一个对象时,更新mCount和id,并把id赋值给mid,按以下规则命名对象,再调用Attack()函数 对象命名规则:
- 若用参数指定名字,则按指定名字命名对象;
- 若无参数,则用"MARTIAN"拼接上id做后缀命名对象;
- 若通过已有对象构造,则按已有对象的名字拼接上id做后缀命名新对象。
(2)析构函数
每个对象消亡前,输出自己的name “was killed! Now alive ”, 更新 mCount并输出;例如:superman was killed! Now alive 6
(3) int getCount() 返回当前系统中火星战士的总数 (4)int getId() 返回火星战士流水号,即历史上一共产生了多少战士 (5)int getMId() 返回火星战士的身份证号mid (6)void Attack() 若当前系统中火星战士的总数>=5, 则输出自己的名字和“Attack!”, 否则输出自己的名字和“Wait!” (7)void rename(string s) 改名为s+mid (8)void rename(const Martian &m) 改名为m的名字+mid
解题思路
- 为所有对象共享,共同维护的数据成员应设为static(静态数据成员),例如火星战士总数和流水号, 静态数据成员必须在类外初始化
- 为所有对象共享,仅涉及静态数据成员的函数,可设为静态成员函数
- 每生成一个对象,需要执行的操作,可放于构造函数
- 每个对象消亡导致的操作,可放于析构函数
探索发现
请在集成开发环境中运行整个程序,阅读主函数,对比分析输出内容,思考以下问题 1 最后一个消亡的对象是谁? 2 观察Declare Martian in loop
后面的输出,体会循环语句的块作用域 3 观察2 copies of superman in function
后面的输出,这是调用copy2函数产生的2个sm, 体会函数的作用域 4 体会构造函数和析构函数何时被调用 5 观察生成火星战士名字后缀,以及当前的火星战士总数,体会静态成员的价值和使用 6 学习对象指针和对象数组的使用与初始化 7 为什么程序结束后,仍然有几个活着的火星战士?如何改进?体验内存溢出的潜在风险 8 为什么要用静态成员计数, 而不用全局计数器呢? 从类的封装性的角度思考一下,对于更复杂的场景,不仅仅有火星战士,还有更多类型的士兵,或者同时有多个用户、或者多个函数、多个进程都可能产生火星战士,使用全局计数器是否存在安全隐患?
编程要求
根据提示,在右侧编辑器补充代码实现类,保证主函数运行正确。
测试说明
平台会对你编写的代码进行测试:
测试输入:3; 预期输出:
globalMartian wait!
MARTIAN2 wait!
MARTIAN3 wait!
MARTIAN4 wait!
--------------------
Declare Martian in 3 loop
MARTIAN5 attack!
MARTIAN5 was killed! Now alive 4
MARTIAN6 attack!
MARTIAN6 was killed! Now alive 4
MARTIAN7 attack!
MARTIAN7 was killed! Now alive 4
--------------------
Superman is coming
superman attack!
--------------------
2 copies of superman in function
superman9 attack!
superman10 attack!
superman10 was killed! Now alive 6
superman9 was killed! Now alive 5
--------------------
hero and it's avatar are coming
hero attack!
hero was killed! Now alive 5
--------------------
killer attack!
angel attack!
king attack!
--------------------
killed:6
alive:8
game is over
king was killed! Now alive 7
angel was killed! Now alive 6
killer was killed! Now alive 5
superman was killed! Now alive 4
globalMartian was killed! Now alive 3
开始你的任务吧,祝你成功!
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class Martian
{
//此外完成类的定义,成员函数只写原型
/BEGIN/
private:
string name;
static int mCount;
static int id;
int mid;
public:
Martian();
Martian(string Name);
Martian(const Martian &m);
~Martian();
static int getCount();
static int getId();
int getMId();
void Attack();
void rename(string s);
void rename(const Martian &m);
end
};
//以下两段代码供参考,学习使用<string>库提供的函数和重载的运算符
void Martian::rename(const Martian &m) // 改名为m的名字加mid作后缀
{
this->name = m.name + to_string(mid); // +运算能够实现拼接; to_string函数能够将整型转换成string对象
}
void Martian :: rename(string s) // 改名为s加mid作后缀
{
this->name = s+to_string(mid);
}
// 请在如下BEGIN-----end之间完成静态数据成员的初始化,并实现Martian类的其余成员函数
//BEGIN/
int Martian::mCount = 0;
int Martian::id = 0;
Martian::Martian() : mid(id++)
{
name = "MARTIAN" + to_string(id);
mCount++;
Attack();
}
Martian::Martian(string Name) : name(Name), mid(id++)
{
mCount++;
Attack();
}
Martian::Martian(const Martian &m) : mid(id++), name(m.name + to_string(id+1))
{
mCount++;
Attack();
}
Martian::~Martian()
{
mCount--;
cout << name << " was killed! Now alive " << mCount << "\n";
}
int Martian::getCount()
{
return mCount;
}
int Martian::getId()
{
return id;
}
int Martian::getMId()
{
return mid;
}
void Martian::Attack()
{
cout << name << " ";
if (mCount >= 5)
cout << "attack!\n";
else
cout << "wait!\n";
}
end
void copy2(const Martian &m )//自定义的普通函数,复制生成2个m
{
Martian s[2] = {Martian(m),Martian(m)};
}
Martian gm("globalMartian"); // 声明全局对象,拥有文件作用域
int main()
{
Martian *p;
int n;
cin >> n;
p = new Martian[n]; // 动态分配内存,生成n个缺省战士
cout << "--------------------\n";
cout << "Declare Martian in 3 loop\n";
for (int i=0; i<3; i++)
{
Martian m; //注意作用域,每轮循环生成1个缺省战士,但进入下一轮循环前就消亡,
}
cout << "--------------------\n";
cout << "Superman is coming\n";
Martian sm("superman"); // 生成superman
cout << "--------------------\n";
cout << "2 copies of superman in function\n";
copy2(sm); //复制生成2个sm 注意函数的块作用域
cout << "--------------------\n";
cout << "hero and it's avatar are coming\n";
{ Martian h1("hero"); } // 生成hero和替身 注意作用域
cout << "--------------------\n";
Martian marray[3]={Martian("killer"), Martian("angel"), Martian("king")}; //声明对象数组,系统自动调用默认构造函数
cout << "--------------------\n";
cout << "killed:" << (Martian::getId()-Martian::getCount()) << endl ; // 消亡的总数
cout << " alive:" << Martian::getCount() << endl; //直接调用静态成员函数显示当前总个数
cout << "game is over\n";//注意消亡的顺序
return 0;
}