C++ 写个游戏引擎—(基础篇)11
今天先介绍 virtual 函数。先定义一个基类 Entity 并定义 GetName 公共方法,返回值为 Entity,然后再定义一个 Player 类,继承 Entity 类。定义一个私有属性 m_Name,并添加构造函数接受参数 name 来为 m_Name 赋值。同样也拥有同名 GetName 函数,函数返回 m_Name 值。
这里代码就不做过的解释了。
如下图中,利用向上转型(在 java 里这么叫),我们可以让类型 Entity 接受其子类 Player 的对象,然后调用对象的 GetName,查看输出结果,发现我们预期不同,这里输出 Entity 而不是 matthew。我们可以进一步验证
为了更清晰分析这种现象,我们可以创建 printName 函数,让他接受 Entity 类型作为参数,然后调用传入对象的 getName 方法来输出信息。我们分别将 p 和 e 作为参数传入函数,运行程序,发现输出 Entity。
这里给大家解释一下原因,这是如果我们将 p 定义为 Entity 类型,他会先查找 Entity 类中是否有 getName 方法。如果有就调用。所以我们看到输出都是 Entity。如果我们想要传入 p 时,输出 matther 而不是 Entity 我们需要怎么做呢。
virtual 提供了解决方案,在 Entity 的 getName 方法前加上 virtual 关键字,表示如果子类用 override 复写这个方法,修改调用复写的方法而不是调用 Entity 的 getName 方法。
Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
我们要在 c++ 中实现相同功能,看一看。我们将 Entity 类中的 GetName 方法声明,并不实现该方法,做法如下图。
修改代码后,发现错误,必须将 Entity 修改为 Player 因为只有 Player 类中才实现了 GetName 方法。
我们写一个 print 方法接受某一个类的实例作为参数,然后调用该对象的 GetClassName 方法
我们可以定义一个接口 Printable 来实现我们的期望,需要注意的是在 c++ 中并没有像 java 中的 interface 关键字来定义接口,我们需要使用 class 来定义一个接口
让 print 方法接受 Printable 类型的对象作为参数。
Entity 可以继承 Printable 这个类(接口)并在 Entity 和 Player 中重新 GetClassName 方法。