C++ - 整个程序持续时间的单个本地类实例
我正在用 C++ 开发一个小游戏引擎,并决定全部以 OOPily 方式完成(大量使用类。) 它的目的是(理论上)跨平台,所以我有一个“引擎”类,它的一个实例是由“操作系统模块”创建的,即 Windows 的 WinMain(我首先为其开发它的平台)。
我有三个主要问题:
创建一个在整个应用程序中只实例化一次的类是否被认为是不好的做法?也许是因为存在某种性能影响或增加了开销使用一个类而不是一堆函数会产生这种情况吗?
我一直计划让 WinMain 创建 Engine 实例作为局部变量。 Engine 类将相当大,包含用于渲染、脚本解析、文件系统内容等的类。基本上,除了操作系统特定代码之外,整个游戏引擎将以某种形式包含在 Engine 类中(可能作为实例)另一个类的。) 在 WinMain 函数中创建非常大的 Engine 类的本地实例是一个坏主意吗?当程序启动时创建类并在程序结束时结束时,创建本地实例是一个坏主意吗?也许new会更好?
我的计划(i/wa)将引擎划分为“模块”,每个模块都由一个类表示。 Engine 类将包含几乎所有其他模块的实例,例如上面提到的渲染、文件系统交互等。从某些角度(性能、设计、可读性?)
感谢您的帮助:)
I'm working on a lil' game engine in C++, and decided to do it all OOPily (heavy use of classes.)
It's intended to be (theoretically) cross-platform, so I have an 'Engine' class, an instance of which is created by the 'OS Module', which is WinMain for Windows (the platform I'm developing it for first.)
I have three main questions:
Is it considered poor practice to create a class that is only going to be instantiated once in the entire application? Perhaps because there is some kind of performance hit or added overhead incurred by using a class rather than a bunch of functions?
I've been planning to have WinMain create the instance of Engine as a local variable. The Engine class will be fairly large, containing classes for rendering, script parsing, file system stuff, etc. Basically, the whole game engine, apart from OS specific code, will be contained in the Engine class in some form (possibly as an instance of another class.) Is creating a local instance of my very large Engine class within the WinMain function a bad idea? Is creating a local instance a bad idea when the class will be created when the program starts, and end when the program ends? Maybe new would be better?
My plan (i/wa)s to divide the engine up into 'modules', each of which is represented by a class. The Engine class would contain an instance of almost all the other modules, like, as mentioned above, rendering, file system interaction, etc. Is using classes as containers for huge modules a bad idea from some perspective (performance, design, readability?)
Thanks for any help :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
游戏引擎不是跨平台的主要候选者,因为它们通常涉及与低级 API(不是跨平台)的有效交互。
类的大小取决于它包含的成员变量,而不是它实现的函数的数量。
堆栈空间通常很小 (http://msdn .microsoft.com/en-us/library/ms686774%28v=vs.85%29.aspx),理论上堆与可用 RAM 一样大。因此,如果您有非常大的东西,请将其存储在堆上(使用 new )。
“启动画面”:不要在程序开始时完成所有工作。用户讨厌当他们运行程序并且屏幕上没有显示任何内容时,因为您的程序正忙于初始化某些内容......
查找惰性实例化,基本上不做可以等待并始终在屏幕上显示某些内容的事情。
至于具体答案:
1. 不,假设没有虚函数,就不应该有性能开销。
2. 请参阅上面的“启动画面”和“有限的堆栈空间”。
3. 模块化通常很好,只需确保每个类确实/代表一个“事物”。但不要有太多的类,以至于你开始忘记它们的名称和用途:)
Game engines are not prime candidates for cross-platform'ness since they usually involve efficient interaction with low-level API's (which are not cross-platofrm).
The size of a class depends on the member variables it contains, not the number of functions it implements.
Stack space is usually small (http://msdn.microsoft.com/en-us/library/ms686774%28v=vs.85%29.aspx) while the heap is theoretically as big as available RAM. So, if you have something really big, store it on the heap (with new).
The "Splash Screen": don't do all the work at the beginning of the program. Users hate it when they run the program and nothing shows on screen because your program is busy initializing something...
Lookup lazy instantiation, basically don't do things that can wait and always show something on screen.
As for specific answers:
1. No, assuming no virtual functions, there should be no performance overhead.
2. See "Splash Screen" and "limited stack space" above.
3. Modularity is generally good, just make sure each class does/represent a single "thing". But don't have so many classes you start forgetting their names and purpose :)
一点也不。这基本上是因为您的 Application 类可以执行继承和封装等操作。不会影响性能或增加开销。
不——这几乎是它应该走的路。为什么要麻烦堆分配呢?您需要自动销毁语义。除非您的类具有非常大的大小,数百 KB 或更多,在这种情况下,基于 RAII 的堆分配更智能,因为堆栈内存非常有限。也就是说,由 sizeof() 报告的每个实例的物理静态大小,不包括动态分配。
这正是面向对象设计的目的——封装,将程序划分为明确定义的、独立的模块,然后实例化每个需要的模块,这正是面向对象编程的思想。类封装的概念的大小通常被认为是无关紧要的,只要它是一个单一的概念即可。清晰的模块化设计非常棒。
我建议对所有依赖于平台的类使用运行时继承,并且最好在运行时动态加载它们(使用操作系统类来执行动态加载)。这强制执行可靠的编译时抽象并允许更高效的编译。
Not at all. This is basically because your Application class can do things like inherit and encapsulate. There's no performance hit or added overhead.
Nope- this is pretty much the way it should go. Why bother heap allocating? You want automatic destruction semantics. Unless your class has a very large size, hundreds of KB or more, in which case an RAII-based heap allocation is smarter, as stack memory is quite limited. That is, a physical per-instance static size as reported by sizeof(), not including dynamic allocations.
This is exactly what object-orientated design is for- encapsulation, and dividing the program up into clearly defined and separated modules, then instantiating each one that you need, is exactly the idea behind object-orientated programming. The size of the concept that a class encapsulates is usually considered to be irrelevant, as long as it's one single concept. A clear modular design is great.
I would recommend using run-time inheritance for all of the platform-dependent ones, and preferably, loading them dynamically at run-time (using the OS class to perform the dynamic loading). This enforces a solid compile-time abstraction and allows for more efficient compilation.
new
)new
unless you absolutely have to)不,这并不被认为是不好的风格。事实上,我知道没有一个应用程序框架是没有它的,著名的单例模式基本上是围绕相同的主题(但不同,请注意)
我无法想象你的类实际上这么大。如果是,则将其放在堆上。然而,无论如何,该类的实际内容很可能都会位于堆上(我有点假设您将使用现有的容器类,100 个容器类中有 99 个会进行动态分配;这适用于 STL 容器,如下所示)好吧)
如果将它们放在数据段中,就像 auto 放在堆栈上或类的成员中一样,会有什么区别?我认为该课程强调模块化,并且可能使您能够更轻松地做事情(例如单元测试,或重用仅网络版本的引擎等)
No it isn't considered bad style. In fact I know no application frameworks that go without one, and the renowned Singleton pattern is basically around the same theme (but different, mind you)
I can't imagine that your class is actually that big. If it is, make it on the heap. However, chances are that the actual contents of that class are going to be on the heap anyway (I'm sort of assuming you'll use existing container classes, that wil 99 out of 100 do dynamic allocation; this goes for STL containers as well)
What difference would it make whether you put them in the data segment, as auto's on the stack or members of a class? I think the class emphesizes the modularity and might enable you to do things more easily (like e.g. unit testing, or reusing the engine for a network-only version etc. etc.)