我应该使用虚拟的“Initialize()"函数来初始化我的类的对象吗?
我目前正在与我的老师讨论班级设计,我们谈到了他大力推广的 Initialize()
函数.示例:
I'm currently having a discussion with my teacher about class design and we came to the point of Initialize()
functions, which he heavily promotes. Example:
class Foo{
public:
Foo()
{ // acquire light-weight resources only / default initialize
}
virtual void Initialize()
{ // do allocation, acquire heavy-weight resources, load data from disk
}
// optionally provide a Destroy() function
// virtual void Destroy(){ /*...*/ }
};
当然,一切都带有可选参数.
Everything with optional parameters of course.
现在,他还强调类层次结构中的可扩展性和使用(他是一名游戏开发人员,他的公司销售游戏引擎),并提出以下论点(逐字记录,仅翻译):
Now, he also puts emphasis on extendability and usage in class hierarchies (he's a game developer and his company sells a game engine), with the following arguments (taken verbatim, only translated):
反对构造函数的论点:
- 不能被派生类覆盖
- 无法调用虚函数
Initialize()
函数的参数:
- 派生类可以完全替代初始化代码
- 派生类可以在自己的初始化过程中随时进行基类初始化
我一直被教导直接在构造函数中进行真正的初始化,并且不提供这样的Initialize()
函数.也就是说,在部署库/引擎方面,我肯定没有他那么多的经验,所以我想我会问好.
I have always been taught to do the real initialization directly in the constructor and to not provide such Initialize()
functions. That said, I for sure don't have as much experience as he does when it comes to deploying a library / engine, so I thought I'd ask at good ol' SO.
那么,支持和反对这种 Initialize()
函数的论据究竟是什么?它是否取决于它应该使用的环境?如果是,请为库/引擎开发人员提供推理,或者,如果可以,甚至是一般的游戏开发人员.
So, what exactly are the arguments for and against such Initialize()
functions? Does it depend on the environment where it should be used? If yes, please provide reasonings for library / engine developers or, if you can, even game developer in general.
编辑:我应该提到,这些类将仅用作其他类中的成员变量,因为其他任何东西对它们都没有意义.对不起.
Edit: I should have mentioned, that such classes will be used as member variables in other classes only, as anything else wouldn't make sense for them. Sorry.
推荐答案
对于 Initialize
:正如你的老师所说的那样,但在精心设计的代码中你可能永远不需要它.
For Initialize
: exactly what your teacher says, but in well-designed code you'll probably never need it.
反对:非标准,如果被虚假使用,可能会破坏构造函数的目的.更重要的是:客户端需要记住调用Initialize
.因此,要么实例在构造时处于不一致状态,要么它们需要大量额外的簿记以防止客户端代码调用其他任何东西:
Against: non-standard, may defeat the purpose of a constructor if used spuriously. More importantly: client needs to remember to call Initialize
. So, either instances will be in an inconsistent state upon construction, or they need lots of extra bookkeeping to prevent client code from calling anything else:
void Foo::im_a_method()
{
if (!fully_initialized)
throw Unitialized("Foo::im_a_method called before Initialize");
// do actual work
}
防止这种代码的唯一方法是开始使用工厂函数.因此,如果您在每个类中都使用 Initialize
,则每个层次结构都需要一个工厂.
The only way to prevent this kind of code is to start using factory functions. So, if you use Initialize
in every class, you'll need a factory for every hierarchy.
换句话说:如果没有必要,不要这样做;始终检查是否可以根据标准结构重新设计代码.当然不要添加 public Destroy
成员,这是析构函数的任务.析构函数可以(并且在继承的情况下,必须)是virtual
.
In other words: don't do this if it's not necessary; always check if the code can be redesigned in terms of standard constructs. And certainly don't add a public Destroy
member, that's the destructor's task. Destructors can (and in inheritance situations, must) be virtual
anyway.
相关文章