-1

我希望用用户非常复杂的初始条件进行模拟。我正在写class A它的成员变量需要在运行之前由用户初始化A.Solve()以获得存储在文件中的结果。初始化相当复杂,需要几个在初始化后不再需要的临时数据结构。因此,我编写了另一个名为class Initializer的类,它存储对class A. 我的代码将如下所示:

 class A {
   friend class Initializer;
   private:
     // member variables storing the state of the system
   public:
     void Solve();
     ...
 };

 class Initializer {
   private:
     A& a
     // Other data structures used in the initialization
     ...
   public:
     // functions called by the user to set up for the initialization
     ...
     Initialize(); // after this is called, a will be ready to solve
 };

 int main(...) {
   A a;
   Initializer init(a);
   // call functions on init to initialize the system
   ...
   init.Initialize();
   a.Solve();
   return 0;
 }

但似乎数据结构init将存在于整个程序的堆栈中。为了防止这种情况,可以这样做:

  A a;
  Initializer *init = new Initializer(a);
  ....
  init.Initialize();
  delete init;
  a.Solve();

或者这看起来没有必要,我应该把所有的东西都包含在里面class A吗?

4

2 回答 2

1

为了回答您最初的想法,通常的解决方案是限制init变量的范围:

A a;
{
    Initializer init(a);
    //...
} // init is destroyed as soon as the scope exits
a.Solve();

您的变体非常脆弱,如果在和new/delete之间抛出任何东西,就会泄漏内存。要解决这个问题,请使用智能指针:newdelete

A a;
std::unique_ptr<Initializer> init(new Initializer(a));
//...
init.reset();
a.Solve();

然而,正如其他人所说,整个设计有点奇怪,可能有点矫枉过正。如果初始化真的很复杂以至于你无法摆脱构造函数,那么你可能想要反过来做:而不是Initializer接受一个参数A并对其进行操作,你应该传递一个完全准备好使用InitializerA' s 构造函数,它将依次复制整体Initializer以保留数据的副本,或者仅复制相关位。Initializer然后可能应该重命名为Config或类似的东西。注意一个Config/Initializer对象现在可以如何被重用来初始化多个A对象,甚至可以在两次A初始化之间进行修改。

不幸的是,在信息如此之少的情况下,很难给你明确的建议。

注意:如果您使用 C++11,您可能会对std::initializer_list启用新的大括号初始化语法感兴趣。根据您的数据的复杂性,它可能比您当前的解决方案涉及更多的工作,但您最终会得到一个非常好的和直观的语法。

于 2013-05-14T16:27:45.090 回答
0

在这里,使用另一个类进行初始化似乎有点过头了。

只需在 A 类构造函数中初始化即可。一旦构造函数执行完成,临时数据结构将被自动释放。

于 2013-05-14T16:27:31.867 回答