我的遗留代码有一个包含许多其他子类作为数据成员的类。其中大多数读取各种输入到子类中的数据成员。它看起来像这样:
MainClass::MainClass(std::string &directory, LogClass &logClass, int mode1, int mode2, int mode3,) :
logClass(logClass),
subClass1(directory, logClass, mode1),
subClass2(directory, logClass),
subClass3(logClass, subClass1, subClass2, mode1, mode2),
subClass4(logClass, subClass1, subClass2, subClass3, mode1, mode2, mode3),
{
if(mode2 == 0)
{
subClass3.init();
}
subClass4.init();
}
在某些子类中,初始化发生在其构造函数的主体中。在其他时候,重要数据成员的初始化发生在mainClass的主体中,如subClass3和subClass4的情况所示。
我正在改变此代码以包含处理先前读入数据的转换的其他子类。其中一些新类需要在构造之前初始化其他类。例如,如果我添加subClass5,则可能需要运行subClass4.init()。但是从代码中可以看出,subClass4.init()并不运行到构造函数的主体。
这里有什么好的政策可以继续前进?我应该将所有初始化从subClass构造函数中拉出到它们自己的init()函数中,并在主类构造函数中正确排序吗?或者我应该将所有初始化移动到subClass构造函数和托盘中并正确排序吗?
我试图为这个问题找出最合适的代码设计。
答案 0 :(得分:0)
像init()
这样的方法有助于将初始化过程委托给以后的时间,从而允许快速启动,因为构造函数不必花费很多时间来执行init()
。如果那些init
方法执行昂贵的操作(如使用密集的CPU周期或获取昂贵的资源),则尤其如此。
另一方面,如果你强加这样的协议,那么添加subClassX
的任何人都必须通过调用子类构造函数确保正确的初始化,然后在这些子类上调用init
。
选择完全属于你,因为这两种方法都有一些优点和缺点。如果你找到更多的优点而不是缺点去吧!
P.S。当然,这假设构造函数正在做足以使子类实例进入最小可用状态。
答案 1 :(得分:0)
构造函数应该始终建立类的不变量,无论是更多还是更少。我强烈认为,一个在构造之后处于无效状态并且必须通过init()
调用初始化的类是不正确的。
出于测试目的,我会考虑将子部件的构造移出类,并将它们提供给构造函数,或者为每个子部件提供工厂。这使您可以为子部件创建模拟,这对单元测试非常有用。