具有const变量的类的编程模型

时间:2013-10-16 19:25:31

标签: c++

我经常要面对包含几个const变量的类的场景,这些变量需要在初始化列表中初始化,但是还需要提前一些其他方法来计算值。

例如,对于以下类:

class Base
{
    protected:
        const int a, b;
    public:
        Base(string file);
};

我希望构造函数通过解析文件来提取一些变量,然后将提取的值分配给const变量(ab)。我过去经常破坏逗号运算符(use comma operator to initialize the base class),但发现更复杂的情况非常不方便。关于一些更优雅的解决方案的任何建议?

1 个答案:

答案 0 :(得分:5)

在需要解析一个对象来计算一个数据成员的值的简单情况下,我会提供一个免费函数并调用:

int ComputeAFromFile (const string& file)
{
  // MAGIC
}

class Base
{
    protected:
        const int a;
    public:
        Base(string file) : a (ComputeAFromFile (file)) {}
};

当你需要解析一个对象来计算多个成员的值时,这会发生故障,但是:

int ComputeAFromFile (const string& file)
{
  // MAGIC
}

int ComputeBFromFile (const string& file)
{
  // MORE MAGIC
}


class Base
{
    protected:
        const int a, b;
    public:
        Base(string file) 
  : 
    a (ComputeAFromFile (file)) 
    b (ComputeBFromFile (file)) 
  {
  }
};

你可以这样做,而且它当然很简单(阅读:易于理解和维护),但在必须解析同一文件两次方面也很昂贵。

相反,我经常要做的是构建一种中间对象,在构造时解析文件一次,并缓存提取的值:

class FileParser 
{
public:
  FileParser (const string& file)
  {
    Parse (file);
  }

  int GetA () const { return mA; }
  int GetB () const { return mB; }

private:
  int mA;
  int mB;

  void Parse (const string& file)
  {
    // MAGIC HAPPENS!
    // Parse the file, compute mA and mB, then return
  }
};

现在,代替Base构建string而不是FileParser

class Base
{
public:
  Base (const FileParser& parser)
  :
    a (parser.GetA()),
    b (parser.GetB())
  {
  }
};

基地就这样构建了:

string file = ...;
Base b (FileParser (file));