我经常要面对包含几个const变量的类的场景,这些变量需要在初始化列表中初始化,但是还需要提前一些其他方法来计算值.
例如,对于以下类:
class Base
{
protected:
const int a, b;
public:
Base(string file);
};
Run Code Online (Sandbox Code Playgroud)
我希望构造函数通过解析文件来提取一些变量,然后将提取的值分配给const变量(a和b).我曾经经常破坏逗号运算符(使用逗号运算符来初始化基类),但发现对于更复杂的情况非常不方便.关于更优雅的解决方案的任何建议?
在需要解析一个对象来计算一个数据成员的值的简单情况下,我将提供一个自由函数并调用:
int ComputeAFromFile (const string& file)
{
// MAGIC
}
class Base
{
protected:
const int a;
public:
Base(string file) : a (ComputeAFromFile (file)) {}
};
Run Code Online (Sandbox Code Playgroud)
当您需要解析一个对象以计算多个成员的值时,这会分解:
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))
{
}
};
Run Code Online (Sandbox Code Playgroud)
你可以做到这一点,它当然很简单(阅读:易于理解和维护),但在必须解析同一文件两次方面也很昂贵.
因此,我经常要做的是构建一种中间对象,在构造时解析文件一次,并缓存提取的值:
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
}
};
Run Code Online (Sandbox Code Playgroud)
现在,而不是Base采取string在建筑,它可以采取FileParser:
class Base
{
public:
Base (const FileParser& parser)
:
a (parser.GetA()),
b (parser.GetB())
{
}
};
Run Code Online (Sandbox Code Playgroud)
而基地就这样构建:
string file = ...;
Base b (FileParser (file));
Run Code Online (Sandbox Code Playgroud)