我正在使用C ++编写一个lil'游戏引擎,并决定将其全部用于OOPily(大量使用类)。 它的目的是(理论上)跨平台,所以我有一个'Engine'类,其实例是由'OS Module'创建的,它是WinMain for Windows(我首先开发它的平台)。
我有三个主要问题:
创建一个只在整个应用程序中实例化一次的类会被认为是不好的做法吗?也许是因为使用时会产生某种性能损失或增加的开销一个类而不是一堆函数?
我一直计划让WinMain创建Engine的实例作为局部变量。 Engine类相当大,包含用于渲染,脚本解析,文件系统等的类。基本上,除了OS特定代码之外,整个游戏引擎将以某种形式包含在Engine类中(可能作为实例)另一个类。)在WinMain函数中创建一个非常大的Engine类的本地实例是一个坏主意吗?在程序启动时创建类时创建本地实例是一个坏主意,并在程序结束时结束?也许 new 会更好?
我的计划(i / wa)将引擎分成'模块',每个模块由一个类表示。 Engine类将包含几乎所有其他模块的实例,如上所述,渲染,文件系统交互等。从某些角度使用类作为大型模块的容器是一个坏主意(性能,设计,可读性?)
感谢您的帮助:)
答案 0 :(得分:4)
游戏引擎不是跨平台性的主要候选者,因为它们通常涉及与低级API(非交叉平台)的有效交互。
类的大小取决于它包含的成员变量,而不是它实现的函数数量。
堆栈空间通常很小(http://msdn.microsoft.com/en-us/library/ms686774%28v=vs.85%29.aspx),而堆在理论上与可用RAM一样大。所以,如果你有一些非常大的东西,把它存放在堆上(用新的)。
“启动画面”:不要在程序开始时完成所有工作。用户在运行程序时讨厌它而屏幕上没有任何内容显示,因为你的程序忙于初始化某些东西...... 查找懒惰的实例化,基本上不做可以等待并始终在屏幕上显示内容的东西。
至于具体答案: 1.不,假设没有虚函数,就不应该有性能开销。 2.参见上面的“启动画面”和“有限的堆栈空间”。 3.模块化通常很好,只要确保每个类都代表一个“事物”。但是,没有那么多课程,你开始忘记他们的名字和目的:)
答案 1 :(得分:2)
它被认为是不好的做法 创建一个只会去的类 在整个实例中被实例化一次 应用?也许是因为有 某种性能受到影响或增加 使用类产生的开销 而不是一堆功能?
完全没有。这基本上是因为您的Application类可以执行继承和封装之类的操作。没有性能损失或增加了开销。
我一直在计划拥有WinMain 创建Engine实例作为 局部变量。 Engine类会 相当大,包含类 用于渲染,脚本解析,文件 系统的东西,等等。基本上, 整个游戏引擎,除了操作系统 具体代码,将包含在 某种形式的Engine类 (可能是另一个人的一个例子 class。)正在创建一个本地实例 我非常大的Engine类 WinMain功能一个坏主意?是 创建一个本地实例是个坏主意 什么时候创建类 程序启动,结束时 程序结束?也许是新的 更好?
不 - 这几乎应该是这样的。为什么要打扰堆分配?您想要自动销毁语义。除非您的类具有非常大的大小,数百KB或更多,在这种情况下,基于RAII的堆分配更加智能,因为堆栈内存非常有限。也就是说,sizeof()报告的物理每实例静态大小,不包括动态分配。
我的计划(i / wa)分开引擎 进入'模块',每个模块都是 由一个班级代表。引擎 class将包含一个实例 几乎所有其他模块,如, 上面提到的,渲染,文件 系统交互等正在使用 类作为大型模块的容器 从某种角度来看是一个坏主意 (性能,设计,可读性?)
这正是面向对象设计的封装,将程序划分为明确定义和分离的模块,然后实例化您需要的每个模块,这正是面向对象编程背后的理念。一个类封装的概念的大小通常被认为是无关紧要的,只要它是一个单一的概念。清晰的模块化设计非常棒。
我建议对所有依赖于平台的应用程序使用运行时继承,最好是在运行时动态加载它们(使用OS类来执行动态加载)。这实现了可靠的编译时抽象,并允许更有效的编译。
答案 2 :(得分:1)
new
)答案 3 :(得分:1)
不,它不被认为是不好的风格。事实上,我知道没有一个应用程序框架,而着名的Singleton模式基本上是围绕同一个主题(但不同,请注意)
我无法想象你的班级实际那么大。如果是,请在堆上进行。但是,很可能这个类的实际内容无论如何都会在堆上(我假设您将使用现有的容器类,其中99个中的99个将进行动态分配;这适用于STL容器孔)
是否将它们放在数据段中,如堆栈上的auto或类的成员,会有什么不同?我认为该类会强调模块化,并可能使您能够更轻松地执行操作(例如,单元测试,或将引擎重新用于网络版本等等)。