我看过很多代码,其中编码人员为类定义了一个init()函数,并在创建实例后的第一件事情就调用它。
在构造函数中完成所有初始化操作是否有害或有限制?
我看过很多代码,其中编码人员为类定义了一个init()函数,并在创建实例后的第一件事情就调用它。
在构造函数中完成所有初始化操作是否有害或有限制?
class stuff
{
public:
stuff(int val1) { init(); setVal = val1; }
stuff() { init(); setVal = 0; }
void init() { startZero = 0; }
protected:
int setVal;
int startZero;
};
private
或final
),因为动态解析可能会使您进入尚未初始化的对象。init()
函数的原因是因为您有许多具有显着共性的构造函数。(在C++的情况下,您仍然需要权衡默认构造,然后赋值与立即使用正确值进行构造之间的差异。)init()
方法。使用super
可以清楚地表明你正在初始化基类,而init
可能会被覆盖。而且,在派生类中定义init
的事实非常强烈地反对在基类中使用它。 - James Kanze这是一种设计选择。您希望保持构造函数尽可能简单,以便轻松阅读其操作。因此,您经常会看到调用其他方法或函数的构造函数,具体取决于语言。这使得程序员可以在不迷失代码的情况下阅读和跟踪逻辑。
就构造函数而言,您可能很快就会遇到希望触发大量事件的情况。良好的设计要求您将这些序列分解为更简单的方法,以使其更易于阅读并在未来更容易维护。
因此,没有任何伤害或限制,这是一种设计偏好。如果您需要在构造函数中完成所有初始化,则可以在那里完成。如果您只需要稍后完成它,则将其放入稍后调用的方法中。无论哪种方式,完全由您决定,并且没有硬性规定。
这是一个与对象构造函数中抛出的异常有关的设计模式。
在C++中,如果从对象构造函数中抛出异常,则语言运行时将认为该对象根本没有被构造。 因此,当对象超出范围时,对象析构函数不会被调用。
这意味着,如果你的构造函数中有类似以下代码:
int *p1 = new int;
int *p2 = new int;
在你的析构函数中加入以下代码:
delete p1;
delete p2;
如果构造函数中p2的初始化由于没有更多可用内存而失败,则new运算符会抛出bad_alloc异常。
此时,即使为p1正确分配了内存,您的对象也没有完全构建。
如果发生这种情况,析构函数将不会被调用,您将泄漏p1。
因此,您在构造函数中放置的代码越多,错误发生导致潜在内存泄漏的可能性就越大。
这就是该设计选择的主要原因,毕竟这并不太疯狂。
有关更多信息,请参见Herb Sutter的博客:C++中的构造函数异常