构造函数何时抛出异常是正确的?(或者在Objective C的情况下:什么情况下init ` er才应该返回nil?)
在我看来,如果对象不完整,构造函数应该失败——因此拒绝创建对象。也就是说,构造函数应该与它的调用者有一个合同,以提供一个函数和工作对象,在哪些方法可以被有意义地调用?这合理吗?
构造函数何时抛出异常是正确的?(或者在Objective C的情况下:什么情况下init ` er才应该返回nil?)
在我看来,如果对象不完整,构造函数应该失败——因此拒绝创建对象。也就是说,构造函数应该与它的调用者有一个合同,以提供一个函数和工作对象,在哪些方法可以被有意义地调用?这合理吗?
当前回答
OO中通常的约定是对象方法确实有功能。
因此,作为一个推论,永远不要从构造函数/init中返回僵尸对象。
僵尸没有功能,可能缺少内部组件。只是一个空指针异常等待发生。
很多年前,我第一次在Objective C中制作僵尸。
就像所有的经验法则一样,也有一个“例外”。
一个特定的接口完全有可能有这样的契约 存在一个允许触发异常的方法“initialize”。 在调用initialize之前,实现此接口的对象可能不会正确响应除属性设置器之外的任何调用。在引导过程中,我在OO操作系统中的设备驱动程序中使用了这种方法,而且它是可行的。
一般来说,你不需要僵尸对象。在Smalltalk这样的语言中,使用变得有点冒火,但是过度使用变得也是一种糟糕的风格。be允许一个对象在原地变成另一个对象,因此不需要信封包装器(高级c++)或策略模式(GOF)。
其他回答
构造函数的任务是使对象进入可用状态。关于这个问题,基本上有两种观点。
一组人赞成两阶段建设。构造函数只是将对象带入一个休眠状态,在这种状态下它拒绝做任何工作。还有一个额外的函数来进行实际的初始化。
我一直不明白这种方法背后的原因。我坚决支持单阶段构造,即对象在构造后完全初始化并可用。
如果单阶段构造函数未能完全初始化对象,则应该抛出。如果对象不能初始化,则必须不允许它存在,因此构造函数必须抛出。
OO中通常的约定是对象方法确实有功能。
因此,作为一个推论,永远不要从构造函数/init中返回僵尸对象。
僵尸没有功能,可能缺少内部组件。只是一个空指针异常等待发生。
很多年前,我第一次在Objective C中制作僵尸。
就像所有的经验法则一样,也有一个“例外”。
一个特定的接口完全有可能有这样的契约 存在一个允许触发异常的方法“initialize”。 在调用initialize之前,实现此接口的对象可能不会正确响应除属性设置器之外的任何调用。在引导过程中,我在OO操作系统中的设备驱动程序中使用了这种方法,而且它是可行的。
一般来说,你不需要僵尸对象。在Smalltalk这样的语言中,使用变得有点冒火,但是过度使用变得也是一种糟糕的风格。be允许一个对象在原地变成另一个对象,因此不需要信封包装器(高级c++)或策略模式(GOF)。
这总是很危险的,特别是当你在构造函数中分配资源时;根据你的语言,析构函数不会被调用,所以你需要手动清理。这取决于在您的语言中对象的生命周期何时开始。
我真正这么做的唯一一次是在某个地方出现了安全问题,这意味着对象不应该,而不是不能,被创建。
由于部分创建的类可能导致的所有麻烦,我认为永远不会。
如果需要在构造过程中验证某些内容,请将构造函数设为私有并定义一个公共静态工厂方法。如果某些东西无效,该方法可以抛出。但是如果一切都检查出来了,它就调用构造函数,保证不会抛出。
参见c++常见问题解答第17.2和17.4节。
一般来说,我发现如果构造函数被编写,那么它们就不会失败,那么移植和维护结果的代码就会更容易,而可能失败的代码则放在一个单独的方法中,该方法返回错误代码并使对象处于惰性状态。