c++ - 更好的类设计

标签 c++ oop inheritance unreal-engine4

我正在使用虚幻引擎 4 编写游戏。该引擎为您提供了几个类。在这个问题中,我将更多地关注类之间的联系,而不是它们的目的。

引擎的类是这样的(“->”表示继承。例如A -> B 表示A继承自B):
ACharacter -> APawn -> AActor -> ... -> UObject
“...”只是无关紧要的类。
UObject类是引擎的主要类,几乎引擎和我的游戏中的每个类最终都继承自UObject,此外它还提供了很多我需要的功能。
继承不是虚拟继承。这对 future 很重要。我无法编辑引擎的任何类。

在我的游戏中有 3 个主要类: 建筑、生活和实体。
建筑继承自 AActor 和实体
Living 继承自 ACharacter 和 Entity

enter image description here

我创建了 Entity 类来关联 Building 或 Living,而无需复制我的代码。例如,Living 类需要提供攻击另一个 Living 或 Building 的功能。所以我可以只创建 2 个函数“AttackLiving”,它有一个 Living 目标参数和一个函数“AttackBuilding”,它有一个 Building 目标参数,这两个函数将具有完全相同的功能。相反,我创建了 Entity 类,因此我只有一个函数 - “AttackEntity”。当然,这只是一个示例,我在整个代码中都使用了 Entity 类,因此我可以同时引用 Living 和 Building。

问题始于 Entity 类。一年前我在实际创建它时犯了一个错误,我没有考虑清楚。问题是 Entity 没有继承自 UObject。同样,UObject 类是引擎的主要类,它提供了我需要的许多功能。因为 Entity 没有继承自 UObject,所以我无法访问我需要的任何功能。

我不能让 Entity 继承自 UObject 或 AActor,因为虚拟继承在这里不起作用。 (同样,引擎类继承不是虚拟继承)

我想过很多可能的解决方案。其中之一是我总是可以根据实体的类型将实体向下转换为建筑或生活,而且我可以使用 UObject 的函数。但这是一个非常丑陋的解决方案,它与实体的目的形成对比——与生活和建筑无关。

我也考虑过在实体中有一个指向 UObject 类的指针,但是这又是一个非常丑陋的解决方案,它并没有解决所有的问题。例如,实体的另一个问题(同样不继承自 UObject):有一个名为“TWeakObjectPtr”的模板类,它在模板中获取一个类,为其创建一个指针并检查该指针是否未在其他任何地方释放由引擎。

TWeakObjectPtr<Entity> entityPointer;

问题是 TWeakObjectPtr 检查模板中给出的类是否继承自 UObject,当然不是,所以我不能使用 TWeakObjectPtr。

综上所述,主要问题是Entity不是继承自UObject。但我确实需要它,这样我才能将生活和建筑联系起来。

如果您能提出一个保留实体的解决方案,我会很高兴。提前致谢!

最佳答案

我从未使用过虚幻引擎,但希望下面的一些想法无论如何都能有用。

改善这种情况的一种方法是断开两个对象层次结构之间的继承链接 - 你的和引擎的:

UOjbect <-- AActor <-- APawn <-- ACharacter
               |                    |
+------+       *                    |
|      |<-- Building                |
|Entity|                            *
|      |<------------------------ Living
+------+

其中*--表示聚合(或组合)。 您的类不继承引擎类,而是聚合适当的引擎对象。

Entity 可以有返回 UObject 的虚方法 getUnreal(),子类将返回 AActorACharacter 对象 适本地。 因此,无论您在何处使用 Entity,您都可以获取引擎对象,只是不是直接获取,而是通过 entiry->getUnreal() 调用。

反过来,您可以从引擎类继承您的类,并使“实体”成为聚合行为而不是基类:

UOjbect <-- AActor <-- APawn <-- ACharacter
               ^                    ^
+------+       |                    |
|      |--* Building                |
|Entity|                            |
|      |------------------------* Living
+------+

在这里您可以在需要引擎对象的地方使用您的Building/Living,但是当您想要引用您自己的逻辑时,您将使用类似建筑->getEntity()。 您可能有不同的 Entity 子类来实现 BuildingLiving 行为。

我还建议您查看设计模式:可重用面向对象软件的元素一书,结构模式一章可能会帮助您找到更多想法。

关于c++ - 更好的类设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46731701/

相关文章:

c++ - 在 Visual Studio 中的项目之间共享预编译头文件

CSS列高不继承

c++ - *non*-const 引用会延长临时人员的生命周期吗?

c++ - glGetString(GL_VERSION) 与请求的版本不匹配

java - 在 C++ 中获取 java.home 的位置

PHP OOP 需要建议

java - 这是一个足够好的抽象还是我可以做得更好?

r - 在 R 中,修改类中的值

java - 为什么抽象属性在 Runnable 接口(interface)的子类中丢失?

Java 继承检查多个变量的值