我应该使用虚拟'Initialize()'函数来初始化我的类的对象吗?

Xeo*_*Xeo 16 c++ initialization

我正在和我的老师讨论关于课堂设计的问题,我们谈到了Initialize()他大力宣传的职能.例:

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(){ /*...*/ }
};
Run Code Online (Sandbox Code Playgroud)

当然,一切都有可选参数.

现在,他还强调了类层次结构中的可扩展性和使用(他是一个游戏开发者,他的公司出售游戏引擎),并带有以下参数(逐字逐句,仅翻译):

反对构造函数的论据:

  • 不能被派生类覆盖
  • 无法调用虚函数

Initialize()功能参数:

  • 派生类可以完全替换初始化代码
  • 派生类可以在自己的初始化期间随时进行基类初始化

我一直被教导直接在构造函数中进行实际初始化,并且提供这样的Initialize()函数.也就是说,我肯定没有他在部署库/引擎时那么多的经验,所以我想我会问好吧.

那么,支持和反对这些Initialize()功能的论点到底是什么?它是否取决于应该使用的环境?如果是,请为图书馆/引擎开发人员提供推理,如果可以的话,请为游戏开发人员提供一般推理.


编辑:我应该提到,这些类将仅用作其他类中的成员变量,因为其他任何东西对它们都没有意义.抱歉.

Fre*_*Foo 7

对于Initialize:老师说的正是如此,但在精心设计的代码中,您可能永远不需要它.

反对:非标准,如果虚假使用可能会破坏构造函数的目的.更重要的是:客户需要记得打电话Initialize.因此,任何一个实例在构建时都会处于不一致状态,或者它们需要大量额外的簿记来防止客户端代码调用其他任何内容:

void Foo::im_a_method()
{
    if (!fully_initialized)
        throw Unitialized("Foo::im_a_method called before Initialize");
    // do actual work
}
Run Code Online (Sandbox Code Playgroud)

防止这种代码的唯一方法是开始使用工厂函数.因此,如果您Initialize在每个类中使用,则每个层次结构都需要一个工厂.

换句话说:如果没有必要,不要这样做; 始终检查代码是否可以根据标准结构重新设计.当然不添加public Destroy成员,这是析构函数的任务.virtual无论如何,析构函数都可以(并且在继承情况下).


ybu*_*ill 5

我反对C++中的'双初始化'.

反对构造函数的论据:

  • 不能被派生类覆盖
  • 无法调用虚函数

如果你必须编写这样的代码,这意味着你的设计是错误的(例如MFC).设计您的基类,以便可以覆盖的所有必要信息通过其构造函数的参数传递,因此派生类可以像这样覆盖它:

Derived::Derived() : Base(GetSomeParameter()) 
{
}
Run Code Online (Sandbox Code Playgroud)


Pup*_*ppy 5

这是一个可怕的,可怕的想法.问问自己 - 如果你Initialize()以后必须打电话,构造函数有什么意义?如果派生类想要覆盖基类,则不要派生.

当构造函数完成时,使用该对象应该是有意义的.如果没有,你做错了.


BЈо*_*вић 1

忘掉Initialize()函数吧——那是构造函数的工作。

当一个对象被创建时,如果构造成功通过(没有抛出异常),则该对象应该被完全初始化。