头歌 实训四:数据的保护与共享进阶项目(构造函数与静态成员)火星战士自主进攻

任务描述

本关任务:仿真和游戏中经常有计算机生成的兵力,从诞生开始就有一定的自主行为。请为火星战士设计和定义类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; 预期输出:

 
  1. globalMartian wait!
  2. MARTIAN2 wait!
  3. MARTIAN3 wait!
  4. MARTIAN4 wait!
  5. --------------------
  6. Declare Martian in 3 loop
  7. MARTIAN5 attack!
  8. MARTIAN5 was killed! Now alive 4
  9. MARTIAN6 attack!
  10. MARTIAN6 was killed! Now alive 4
  11. MARTIAN7 attack!
  12. MARTIAN7 was killed! Now alive 4
  13. --------------------
  14. Superman is coming
  15. superman attack!
  16. --------------------
  17. 2 copies of superman in function
  18. superman9 attack!
  19. superman10 attack!
  20. superman10 was killed! Now alive 6
  21. superman9 was killed! Now alive 5
  22. --------------------
  23. hero and it's avatar are coming
  24. hero attack!
  25. hero was killed! Now alive 5
  26. --------------------
  27. killer attack!
  28. angel attack!
  29. king attack!
  30. --------------------
  31. killed:6
  32. alive:8
  33. game is over
  34. king was killed! Now alive 7
  35. angel was killed! Now alive 6
  36. killer was killed! Now alive 5
  37. superman was killed! Now alive 4
  38. 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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

panjyash

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值