与硬件接口的C++构造函数应该真正起作用吗?

wad*_*rld 29 c++ hardware constructor

可能重复:
在构造函数中应该完成多少工作?

我心里想着一些建议,但我不记得推理.

我似乎记得在某些时候阅读一些建议(不记得来源)C++构造函数不应该做真正的工作.相反,他们应该只初始化变量.建议继续解释实际工作应该在某种init()方法中完成,在创建实例后单独调用.

情况是我有一个代表硬件设备的类.构造函数调用查询设备的例程以构建描述设备的实例变量对我来说具有逻辑意义.换句话说,一旦new实例化对象,开发人员就会收到一个准备好使用的对象,不需要单独调用object-> init().

施工人员不应该做真正的工作有充分的理由吗?显然它可能会减慢分配时间,但如果在分配后立即调用单独的方法,则不会有任何不同.

只是想弄清楚我目前没有考虑的问题可能导致了这样的建议.

Ext*_*kun 26

我记得更有效的C++中的Scott Meyers建议不要使用多余的默认构造函数.在那篇文章中,他还谈到了使用像Init()这样的方法来"创建"对象.基本上,您已经引入了一个额外的步骤,将责任放在类的客户端上.此外,如果要创建所述对象的数组,则每个对象都必须手动调用Init().你可以有一个构造函数可以在里面调用的Init函数来保持代码整洁,或者如果你实现了一个Reset(),你可以调用该对象,但是根据经验,最好删除一个对象并重新创建它而不是尝试重置它的值为默认值,除非实时创建和销毁对象多次(例如,粒子效果).

另请注意,构造函数可以执行正常函数无法执行的初始化列表.

人们可能会警告不要使用构造函数进行大量资源分配的一个原因是因为在构造函数中捕获异常很困难.但是,有很多方法可以解决它.否则,我认为构造函数是为了做他们应该做的事情 - 为其初始执行状态准备一个对象(对象创建很重要的是资源分配).

  • 那将是Scott Meyers - Sid Meier是文明人:) (26认同)

War*_*pin 18

不在构造函数中"工作"的一个原因是,如果从那里抛出异常,则不会调用类析构函数.但是如果你使用RAII原则并且不依赖你的析构函数来清理工作,那么我觉得最好不要引入一个不需要的方法.

  • 我想补充说,即使构造函数抛出每个完全构造的成员变量也会调用其derstructor(因此如果你在构造函数的代码块中,所有成员都将被正确销毁). (8认同)

pax*_*blo 9

取决于你的实际工作意味着什么.构造函数应该将对象置于可用状态,即使该状态是一个标志意味着它尚未初始化:-)

我没有做过实际工作的唯一理由是,构造函数失败的唯一方法是使用异常(并且在这种情况下不会调用析构函数).没有机会返回一个很好的错误代码.

你要问自己的问题是:

对象无需调用init方法即可使用吗?

如果答案是"否",我将在构造函数中完成所有工作.否则,当用户实例化但尚未初始化并返回某种错误时,您将不得不捕获这种情况.

当然,如果你可以重新初始化设备,你应该提供某种init方法,但是,在这种情况下,如果满足上述条件,我仍然会从构造函数中调用该方法.


Nea*_*len 7

除了有关异常处理的其他建议之外,连接到硬件设备时要考虑的一件事是,您的类将如何处理设备不存在或通信失败的情况.

在无法与设备通信的情况下,您可能需要在类上提供一些方法来执行以后的初始化.在这种情况下,仅实例化对象然后运行初始化调用可能更有意义.如果初始化失败,您可以保留对象并尝试稍后再次初始化通信.或者您可能需要处理初始化后通信丢失的情况.在任何一种情况下,您可能都想要考虑如何设计类来处理通常的通信问题,这可能有助于您决定在构造函数中执行的操作与初始化方法相比.

当我实现了与外部硬件通信的类时,我发现实例化"断开连接"的对象更容易,并提供连接和设置初始状态的方法.这通常提供了与设备连接/断开/重新连接的更大灵活性.