冀教网 - 河北教师网站 - 专注于冀教版课本资源

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 81|回复: 0

Coursera课程笔记----C++程序设计----Week6

[复制链接]

3万

主题

3万

帖子

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118679
发表于 2020-5-24 00:59 | 显示全部楼层 |阅读模式
多态与虚函数(week 6)

多态与虚函数的基本概念

虚函数


  • 在类的定义中,前面有virtual关键字的成员函数就是虚函数
    1. class base{  virtual int get();};int base::get(){}
    复制代码
  • virtual关键字只用在类定义里的函数声明中,写函数体时不用
  • 构造函数和静态成员函数不能是虚函数
多态的表现形式(一)


  • 派生类的指针可以赋值给基类指针
  • 通过基类指针调用基类和派生类中的同名虚函数时:

    • 若该指针指向一个基类的对象,那么被调用的是基类的虚函数
    • 若该指针指向一个派生类的对象,那么被调用的是派生类的虚函数
    这个机制就叫做“多态

多态的表现形式(二)


  • 派生类的对象可以赋给基类引用
  • 通过基类引用调用基类和派生类中的同名虚函数时:

    • 若该引用引用的是一个基类的对象,那么被调用的是基类的虚函数
    • 若该引用引用的是一个派生类的对象,那么被调用的是派生类的虚函数
    这个机制就叫做“多态”

多态的作用

在面向对象的程序设计中使用多态,能够增强程序的可扩充性,即程序需要修改或增加功能的时候,需要改动和增加的代码较少。
使用多态的游戏程序实例

基本思路


  • 为每个怪物类编写 Attack、FightBack和Hurted成员函数
  • Attack函数表现攻击动作,攻击某个怪物,并调用被攻击怪物的Hurted函数,以减少被攻击怪物的生命值,同时也调用被攻击怪物的FightBack成员函数,遭受被攻击怪物的反击
  • Hurted函数减少自身生命值,并表现受伤动作
  • FightBack成员函数表现反击动作,并调用被反击对象的Hurted成员函数,使被反击对象受伤。
  • 设置基类CCreature,并且使CDragon,CWolf等其他类都从CCreature派生而来。
    我的关键词 Coursera课程笔记----C++程序设计----Week6  新闻资讯 5ec4c907c2a9a83be566ae7f

非多态的实现方法


  • 有n种怪物,CDragon类中就会有n个Attack成员函数,以及n个FightBack成员函数,对其他类也是如此,非常麻烦。
多态的实现方法
  1. //基类CCreatureclass CCreature{  protected:  int m_nLifeValue,m_nPower;  public:  virtual void Attack(CCreature* pCreature){};  virtual void Hurted(int nPower){};  virtual void FightBack(CCreature *pCreature){};};//派生类 CDragonclass CDragon:public CCreature{  public:  virtual void Attack(CCreature* pCreature){};  virtual void Hurted(int nPower){};  virtual void FightBack(CCreature *pCreature){};};void CDragon::Attack(CCreature *p){  //省略一些代码  p->Hurted(m_nPower);//多态  p->FightBack(this);//多态}void CDragon::Hurted(int nPower){    //省略一些代码  m_nLifeValue -= nPower;}void CDragon::FightBack(CCreature *p){  p->Hurted(m_nPower/2);//多态}
复制代码
多态实现方法的优势


  • 如果想要增加新的怪物种类,只需要编写新类,原有的类可以原封不动
更多多态程序实例

例一:几何体处理程序


  • 几何形体处理程序:输入若干个几何形体的参数,要求按面积排序输出。输出时要指明形状。
  • 输入

    • 第一行是几何形体数目n(不超过100),下面有n行,每行以一个字母c开头
    • 若c是‘R’,则代表一个矩形,本行后面跟着两个整数,分别是矩形的宽&高
    • 若c是‘C’,则代表一个圆,本行后面跟着一个整数代表其半径
    • 若c是‘T',则代表一个三角形,本行后面跟着三个整数,代表三条边的长度

  • 输出

    • 按面积从小到大依次输出每个几何形体的种类及面积。每行一个几何形体,输出格式为

      • 形体名称:面积


  1. #Include #include #include using namespace std;class CShape{  public:  virtual double Area() = 0;//纯虚函数  virtual void PrintInfo() = 0;};class CRectangle:piblic CShape{  public:  int w,h;  virtual double Area();  virtual void PrintInfo();}class CCircle:piblic CShape{  public:  int r;  virtual double Area();  virtual void PrintInfo();}class CTriangle:piblic CShape{  public:  int a,b,c;  virtual double Area();  virtual void PrintInfo();}double CRectangle::Area(){  return w*h;}void CRectangle::PrintInfo(){  cout pt->b >> pt->c;        pShapes[i] = pt;        break;    }  }  qsort(pShapes,n,sizeof(CShanpe*),MyCompare);  for(i = 0;i < n;i++)    pSHapes[i] ->PrintInfo();  return 0;}int MyCompare(const void *s1, const void *s2){  double a1,a2;  CShape* *p1; //s1,s2是void*,不可写“*s1”来取得s1指向的内容  CShape* *p2;  p1 = (CShape**)s1;//s1,s2指向pSHapes数组中的元素,数组元素的类型是CShape*  p2 = (Cshape**)s2;//故p1,p2都是指向指针的指针,类型为CShape **  a1 = (*p1)->Area();//*p1的类型是CShape*,是基类指针,此句为多态  a2 = (*p2)->Area();  if(a1 < a2)    return -1;  else if(a2 < a1)    return 1;  else    return 0;}//如果添加新的几何形体,只需要从CShape派生出CPentagon,以及在main中的switch语句中增加一个case即可
复制代码

  • 用基类指针数组存放指向各种派生类对象的指针,然后遍历该数组,就能对各个派生类对象做各种操作,是很常用的做法。
例二

[code]class Base{  public:  void fun1(){this->fun2();}//this是基类指针,fun2是虚函数,所以是多态  virtual void fun2(){cout Loyal_reduce >> Total_Minutes;        Command COM[2] = {Command(M,0),Command(M,1)};        vector Citys;        for (int i = 0; i < N; ++i){            City temp(i + 1);            Citys.push_back(temp);        }        for (int i = 0; i < 5; ++i)            cin >> Life_Make;        for (int i = 0; i < 5; ++i)            cin >> Attack_;        cout  Total_Minutes) break;//第20分钟            else                for (int i = 0; i < N; ++i) Citys.Add_Life();            Minute = 30;            if (Hour * 60 + Minute > Total_Minutes) break;//第30分钟            else                for (int i = 0; i < N; ++i) Citys.Minute_30();            Minute = 35;            if (Hour * 60 + Minute > Total_Minutes) break;//第35分钟            else            if (N > 1){//city数大于1时才会发生arrow事件                City* Cp[2] = {};                Cp[0] = NULL; Cp[1] = &Citys[1];                Citys[0].Minute_35(Cp);                for (int i = 1; i < N-1; ++i){                    Cp[0] = &Citys[i-1]; Cp[1] = &Citys[i+1];                    Citys.Minute_35(Cp);                }                Cp[0] = &Citys[N-2]; Cp[1] = NULL;                Citys[N-1].Minute_35(Cp);            }            Minute = 38;            if (Hour * 60 + Minute > Total_Minutes) break;//第38分钟            else                for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)                    (*i).Minute_38();            Minute = 40;            if (Hour * 60 + Minute > Total_Minutes) break;//第40分钟            else{                for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)//战斗及输出                    (*i).Battle();                for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)//奖励生命元                    (*i).Reward(0);                for (vector::reverse_iterator i = Citys.rbegin(); i != Citys.rend(); ++i)                    (*i).Reward(1);                for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)//获取city生命元                    (*i).Win_get();            }            Minute = 50;            if (Hour * 60 + Minute > Total_Minutes) break;//第50分钟            else                COM[0].Report_life();COM[1].Report_life();            Minute = 55;            if (Hour * 60 + Minute > Total_Minutes) break;//第55分钟            else{                for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)                    (*i).Warrior_report(0);                COM[1].Report();COM[0].Report();                for (vector::iterator i = Citys.begin(); i != Citys.end(); ++i)                    (*i).Warrior_report(1);            }            Minute = 0;            Hour++;        }    }}int main(){// freopen("d:\\anser.txt", "w", stdout);    Game_Start();// fclose(stdout);    return 0;}bool Warrior::Minute_5(){    if (name == lion) if (Loyal

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|冀教网 - 河北教师网站 - 专注于冀教版课本资源  

GMT+8, 2020-5-27 14:58 , Processed in 1.301211 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表