我经常要面对包含几个const变量的类的场景,这些变量需要在初始化列表中初始化,但是还需要提前一些其他方法来计算值。
例如,对于以下类:
class Base
{
protected:
const int a, b;
public:
Base(string file);
};
我希望构造函数通过解析文件来提取一些变量,然后将提取的值分配给const变量(a
和b
)。我过去经常破坏逗号运算符(use comma operator to initialize the base class),但发现更复杂的情况非常不方便。关于一些更优雅的解决方案的任何建议?
答案 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));