游戏软件的开发最能体现面向对象设计方法的优势。游戏中的人物、道具、建筑物、场景等都是很直观的对象,游戏运行的过程就是这些对象相互作用的过程。每个对象都有自己的属性和方法,不同对象也可能有共同的属性和方法,特别适合使用继承、多态等面向对象的机制。下面就以“魔法门”游戏为例来说明多态在增加程序可扩展性方面的作用。

“魔法门”游戏中有各种各样的怪物,如骑士、天使、狼、鬼,等等。每个怪物都有生命力、攻击力这两种属性。怪物能够相互攻击。一个怪物攻击另一个怪物时,被攻击者会受伤;同时被攻击者会反击,使得攻击者也受伤。但是反击只有其自身攻击力的一半。而且还有各自的攻击、反击动作(省略)

不用多态:

class C_dragon{  //龙
private:
int power; //攻击力
int life_value; //生命值
public:
void Attack(C_wolf* p); //攻击 狼 的成员函数
void Attack(C_ghost* p); //攻击 鬼 的成员函数
//......其他Attack重载函数
//表现受伤的成员函数
void Hurted(int n_power); //被攻击,生命值降低的成员函数
void Fight_back(C_wolf* p); //反击 狼 的成员函数
void Fight_back(C_ghost* p); //反击 鬼 的成员函数
//......其他Fight_back重载函数
}; void C_dragon::Attack(C_wolf* p){
p->Hurted(power);
p->Fight_back(this);
}
void C_dragon::Attack(C_ghost* p){
p->Hurted(power);
p->Fight_back(this);
}
void C_dragon::Hurted(int n_power){
life_value-=n_power;
}
void C_dragon::Fight_back(C_wolf* p){
p->Hurted(power/2);
}
void C_dragon::Fight_back(C_ghost* p){
p->Hurted(power/2);
}

实际上,如果游戏中有n种怪物,C_dragon类中就会有n个Attack成员函数,n个Fight_back成员函数。对于其他类,如C_wolf类等,也是这样。
  以上为非多态的实现方法。在增加怪物种类多的时候,工作量会比较大。例如增加怪物“雷鸟”,除了编写一个C_bird类外,所以的类都需要增加一下两个成员函数,用以对“雷鸟”实施攻击,以及被“雷鸟”攻击时的反击:

void Attack(C_bird* p){
p->Attack(power);
p->Fight_back(this);
};
void Fight_back(C_bird* p){
p->Hurted(power/2)
};

实际上,在非多态的实现中,使代码更精简的做法是将C_dragon、C_wolf等类的共同特点抽取出来,形成一个C_creature类,然后再从C_creature类派生出C_dragon、C_wolf等类,但是由于每种怪物的表现动作不同,这些类还要实现各自的Hurted、Attack、Fight_back成员函数。因此,如果没有利用多态机制,那么即便引入基类C_creature,对程序的可扩充性也没有太大帮助。

使用多态:

设置一个基类C_creature,概括所有怪物的共同科殿。所以具体的怪物类,如C_dragon、C_wolf、C_ghost等,均从C_creature类派生而来。

C_creature:

class C_creature{        //“怪物”类
protected:
int life_value,power;
public:
virtual void Attack(C_creature* p){};
virtual void Hurted(int n_power){};
virtual void Fight_back(C_creature* p){};
};

可以看到,基类C_creature中只有一个Attack成员函数,也只有一个Fight_back成员函数。

实际上,所以C_creature类的派生类也都只有一个Attack成员函数和一个Fight_back成员函数。例如 C_dragon类:

class C_dragon::public C_creature{
public:
virtual void Attack(C_creature* p){
p->Attack(power);
p->Fight_back(this);
};
virtual void Hurted(int n_power){
life_value-=n_power;
};
virtual void Fight_back(C_creature* p){
p->Hurted(power/2)
};
};

C_dragon类的成员函数中省略了表现动作的那部分代码。其他类的写法和C_dragon类类似,只是实现动作的代码不同。

在上述多态的写法中,当需要增加新怪物“雷鸟”时,只需要编写新类C_bird即可。不需要在已有的类中专门为新怪物增加:

void Attack(C_bird* p){
p->Attack(power);
p->Fight_back(this);
};
void Fight_back(C_bird* p){
p->Hurted(power/2)
}; 

这两个成员函数,也就是说,其他类根本不用修改。这样一来跟前面的非多态方法相比,程序的可扩充性大大提高了。

新标准c++程序设计

多态的作用-游戏编程展示------新标准c++程序设计的更多相关文章

  1. 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计

    类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...

  2. 多态实现的原理------新标准c++程序设计

    “多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespac ...

  3. 类型转换构造函数 及使用explicit避免类型自动转换------新标准c++程序设计

    类型转换构造函数:  除复制构造函数外,只有一个参数的构造函数一般可以称作类型转换构造函数,因为这样的构造函数能起到类型自动转换的作用.例如下面的程序: #include<iostream> ...

  4. this指针------新标准c++程序设计

    背景:   c++是在c语言的基础上发展而来的,第一个c++的编译器实际上是将c++程序翻译成c语言程序,然后再用c语言编译器进行编译.c语言没有类的概念,只有结构,函数都是全局函数,没有成员函数.翻 ...

  5. 指针和动态分配内存 (不定长度数组)------新标准c++程序设计

    背景: 数组的长度是定义好的,在整个程序中固定不变.c++不允许定义元素个数不确定的数组.例如: int n; int a[n]; //这种定义是不允许的 但是在实际编程中,往往会出现要处理的数据数量 ...

  6. 正确处理类的复合关系------新标准c++程序设计

    假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类.狗是有主人的,主人也有狗.假定狗只有一个主人,但一个主人可以有最多10条狗.该如何处理“主人”类和“狗”类的关系呢?下面是 ...

  7. 类与类之间的两种关系------新标准c++程序设计

    在c++中,类和类之间有两种基本关系:复合关系和继承关系. 复合关系也称为“has a”关系或“有”的关系,表现为封闭类,即一个类以另一个类的对象作为成员变量. 继承关系也称为“is a”关系或“是” ...

  8. 复制构造函数被调用的三种情况------新标准c++程序设计

    1.当用一个对象去初始化同类的另一个对象时,会引发复制构造函数被调用.例如,下面的两条语句都会引发复制构造函数的调用,用以初始化c2. C c2 (c1); C c2=c1; 这两条语句是等价的.注意 ...

  9. 析构函数的调用------新标准c++程序设计

    示例1: #include<iostream> using namespace std; class CDemo{ public: ~CDemo(){cout<<"d ...

随机推荐

  1. Unity3D的坑系列:打包Assetbundle丢失Shader问题(贴图显示不了)

    从Unity4.2开始,为了减少首包大小,不会默认将所有Shader引擎加到游戏程序中,据Unity技术支持人员所说,Unity会将Shader引擎打包到Assetbundle资源中,但是我测试发现不 ...

  2. oracle显示数据库名和表名

    oracle查看表名 select table_name from user_tables; select table_name from dba_tables; select * from all_ ...

  3. python's twenty ninthday for me 模块和包

    模块 和 脚本的 区别:   如果一个py文件被导入了,就是一个模块. 如果这个py文件被直接执行,这个被直接执行的文件就是一个脚本. 模块:1,没有具体的调用过程.2,能对外提供功能. pyc文件: ...

  4. Python 正则表达式之选择

    In [4]: import re In [5]: re.findall(r"\d+","jjj1234mm222")Out[5]: ['1234', '222 ...

  5. 10.solr学习速成之高亮显示

    Solr高亮显示的三种实现 高亮显示在搜索中使用的比较多,比较常用的有三种使用方式,如果要对某field做高亮显示,必须对该field设置stored=true .          第一种是普通的高 ...

  6. Git第三方仓库安装方式(IUS)

    1.安装使用里面说的自动化安装脚本 curl https://setup.ius.io | sh 2.然后可以看到 git2u相关内容 yum search git 3.执行安装,并查看下版本 yum ...

  7. python并发之multiprocessing

    由于GIL(全局解释锁)的问题,python多线程并不能充分利用多核处理器.如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.multiprocessing可以给每个进程赋 ...

  8. 无法安装 Microsoft Visual Studio 2010 Service Pack 1

    解决办法: 32 位系统删除:HKEY_LOCAL_MACHINE\Software\Microsoft\VSTO Designtime Setup\ 64 位系统删除:HKEY_LOCAL_MACH ...

  9. 转:创建一个javaweb项目,以及导出war包

    一.使用IDEA创建一个javaweb项目 1.File->New Project选择Web Application 1 2 然后填写好路径和项目名称,点击确定. 1 2 2.先看一下刚创建好的 ...

  10. axis调用webservice客户端开发

    第一步:wsdl2Java.bat文件编写 Axis_Lib表示依赖的jar包路径 Output_Path表示生成的class路径 Package包名 还需要手动更改 -p %Package%表示we ...