我正在用C ++编写一个物理模拟(Ising模型),它在方格上运行。我的程序的核心是我的Ising类,它带有一个构造函数,用于调用晶格的行和列尺寸。我有另外两种方法来设置系统的其他参数(温度和初始状态),在进化系统之前必须调用!因此,例如,示例程序可能看起来像这样
int main() {
Ising system(30, 30);
system.set_state(up);
system.set_temperature(2);
for(int t = 0; t < 1000; t++) {
system.step();
}
return 0;
}
如果在system.step()之前未调用system.set _ *()方法,则system.step()会抛出异常,提醒用户注意该问题。我用这种方式实现它来简化我的构造函数;这是不好的做法吗?
答案 0 :(得分:13)
建议尽可能将所有必需参数放在构造函数中(当然有例外,但这些应该很少见 - I have seen one real-world example到目前为止)。通过这种方式,您可以更轻松,更安全地使用课程。
另请注意,通过简化构造函数,您可以使客户端代码更加复杂,哪种IMO是一个不好的权衡。构造函数只编写一次,但调用者代码可能需要写入多次(增加了要编写的代码量和错误的可能性)。
答案 1 :(得分:2)
完全没有,IMO。从外部文件加载数据时我面临同样的问题。创建对象(即,调用它们各自的ctors)时,数据仍然不可用,并且只能在稍后阶段检索。因此,我将初始化分为不同阶段:
这对我正在开发的框架非常具体,但是没有办法只使用构造函数处理所有内容。
但是,如果您在调用ctor时知道变量,最好不要使代码复杂化。对于任何使用您代码的人来说,这都是一个令人头疼的问题。
答案 2 :(得分:1)
IMO如果必须每次都调用所有这些初始化步骤,那么这种形式很糟糕。精心设计的软件的目标之一是最大限度地减少搞砸的机会,并且在对象“可用”之前必须调用多个方法只会使得更难以正确使用。如果这些调用是可选的,那么将它们作为单独的方法就可以了。
分享并享受。
答案 3 :(得分:1)
类中的整个点是呈现某种抽象。作为一个类的用户,我应该能够假设它的行为就像它所模拟的抽象一样。
部分原因是类必须始终有效。一旦创建了对象(通过调用构造函数),该类必须处于有意义的有效状态。它应该可以使用了。如果不是,那么它就不再是一个好的抽象。
答案 4 :(得分:0)
如果必须以特定的顺序调用初始化方法,那么我会用自己的方法将调用包装到它们中,因为这表明这些方法本身不是原子的,因此应该如何调用它们的“知识”在一个地方举行。
嗯,这是我的意见,无论如何!
答案 5 :(得分:0)
我想说如果你计划在同一个格子上初始化并运行多个瞬态,那么设置初始条件应该与构造函数分开。
如果运行瞬态并停止,则可以在构造函数中移动设置初始条件,但这意味着您必须传入参数值才能执行此操作。
我完全同意在调用构造函数后对象应该100%准备好使用的想法,但我认为这与设置初始温度场的物理学分开。该对象可以完全可用,但问题中的每个节点都处于绝对零度的相同温度。从传热的角度来看,绝缘体中的均匀温度场并不是很重要。
答案 6 :(得分:0)
正如另一位评论员指出的那样,不得不调用一堆初始化函数。我会在课堂上把它包起来:
class SimulationInfo
{
private:
int x;
int y;
int state;
int temperature;
public:
SimulationArgs() : x(30), y (30), state(up), temperature(2) { }; // default ctor
// custom constructors here!
// properties
int x() const { return x; };
int y() const { return y; };
int state() const { return state; };
int temperature() const { return temperature; };
}; // eo class SimulationInfo
class Simulation
{
private:
Ising m_system;
public:
Simulation(const SimulationInfo& _info) : m_system(_info.x(), _info.y())
{
m_system.set_state(_info.state());
m_system.set_temperature(_info.temperature());
} // eo ctor
void simulate(int _steps)
{
for(int step(0); step < _steps; ++steps)
m_system.step();
} // eo simulate
}; // eo class Simulation
还有其他方面,但这使得默认设置中的内容更加可用:
SimulationInfo si; // accept all defaults
Simulation sim(si);
sim.simulate(1000);