In simple cases where you need to parse one object to compute the value for one data member, I'd supply a free function and call that:
int ComputeAFromFile (const string& file)
{
// MAGIC
}
class Base
{
protected:
const int a;
public:
Base(string file) : a (ComputeAFromFile (file)) {}
};
This breaks down when you need to parse one object to compute the values of more than one member, however:
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))
{
}
};
You could do this, and it's certainly simple (read: easy to understand & maintain), but its also costly in terms of having to parse the same file twice.
So instead, what I'll often do is build a kind of intermediary object that parses the file once on construction, and caches the extracted values:
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
}
};
Now, instead of Base
taking a string
on construction, it can take a FileParser
:
class Base
{
public:
Base (const FileParser& parser)
:
a (parser.GetA()),
b (parser.GetB())
{
}
};
And Base is constructed thusly:
string file = ...;
Base b (FileParser (file));