什么是多态?
简单来说,就是不同继承关系的派生类对象,去调用同一个函数,产生不同的行为。
多态在游戏中的应用场合?
比如有一个游戏,里面有不同的怪物,每个怪物都可以攻击,走路,idel。在编写怪物逻辑的时候,就可以先编写一个Creat基类,在基类中将每个怪物共有的这些方法定义为虚函数。每个怪物是一个派生类,在怪物各自的派生类中编写怪物相应的方法即可。这样简化了代码的书写量,也提高了拓展性,还符合开闭原则。
基类函数加不加virtual对程序有什么影响?
如果父类不加virtual,就是静态绑定,调用的是父类的方法。如果加了virtual,就是动态绑定,会绑定子类的方法。
当基类中的函数加virtual,派生类中的同名函数都会默认为virtual,即使没有声明。
#include <bits/stdc++.h>
using namespace std;
class Base {
public:
void Test() {
cout << "基类" << endl;
}
};
class Derived :public Base {
public:
void Test() {
cout << "派生类" << endl;
}
};
void main()
{
Base* b = new Derived();
b->Test();
}
输出 基类
当基类函数中加了virtual
#include <bits/stdc++.h>
using namespace std;
class Base {
public:
virtual void Test() {
cout << "基类" << endl;
}
};
class Derived :public Base {
public:
void Test() {
cout << "派生类" << endl;
}
};
void main()
{
Base* b = new Derived();
b->Test();
}
输出 派生类
为什么会出现这样的情况?这里引出静态绑定和动态绑定两个概念。
静态绑定
#include <bits/stdc++.h>
using namespace std;
class Base {
public:
void Test() {
cout << "基类" << endl;
}
};
class Derived :public Base {
public:
void Test() {
cout << "派生类" << endl;
}
};
void main()
{
Base* b = new Base();//b的静态类型是声明他的类型Base,动态类型也是Base
Derived* d = new Derived();//d的静态类型是声明他的类型Derived,动态类型也是Derived
Base* bb = new Derived();//bb的静态类型是声明他的类型Base,动态类型是Derived
Base* bn = NULL;//bn的静态类型是Base,没有动态类型
b->Test();
d->Test();
bb->Test();
bn->Test();//不用奇怪为什么空指针也可以调用函数,因为这在编译期就确定了,和指针空不空没关系
}
输出
基类
派生类
基类
基类
因为基类中的函数不是virtual,那么不管基类的对象指向哪里,对函数的调用都是在定义对象的时候已经决定,这就是静态绑定。静态绑定发生在编译期。
动态绑定
#include <bits/stdc++.h>
using namespace std;
class Base {
public:
virtual void Test() {
cout << "基类" << endl;
}
};
class Derived :public Base {
public:
void Test() {
cout << "派生类" << endl;
}
};
void main()
{
Base* b = new Base();//b的静态类型是声明他的类型Base,动态类型也是Base
Derived* d = new Derived();//d的静态类型是声明他的类型Derived,动态类型也是Derived
Base* bb = new Derived();//bb的静态类型是声明他的类型Base,动态类型是Derived
Base* bn = NULL;//bn的静态类型是Base,没有动态类型
b->Test();
d->Test();
bb->Test();
//bn->Test();//运行报错 空指针 因为动态绑定对函数的调用之只能等到运行期才能确定
}
输出
基类
派生类
派生类
如果基类中的函数是虚函数,那么所有的调用都会等到运行的时候根据其指向的对象的类型才能确定,比起静态绑定会有少许的性能损失,但是实现了多态特性。动态绑定发生在运行期。