Reputation: 357
In C++ how do I make a variable constant but assign to it in a constructor? The reason I want to do this is because I'm trying to use data driven design by putting all my data into an XML file and then loading that data into variables. The problem is that I can't load the values in a initialization list so I have to do it in the constructor (or elsewhere), but then the variables aren't constant.
Here's an XML file:
<weapons>
<pistol>
<damage>5.0</damage>
...
</pistol>
...
</weapons>
Then I've got a class like:
header
class Weapon
{
public:
Weapon();
const float damage;
};
source
#include "Weapon.h"
Weapon::Weapon()
{
//load damage value into damage variable
}
Because the damage variable is constant I can't do anything with it in the constructor, only in the initializer list, but obviously I can't execute code like reading an XML file in the initializer list. So even though the variable will never change should I just not make it constant or is there a proper way to leave it constant and do what I need?
Upvotes: 0
Views: 1492
Reputation: 45470
You could have a xml parser, for example:
class WeaponXMLParser
{
public:
WeaponXMLParser(const std::string& filename);
float getDamage();
};
Initialize const member in initializers list:
Weapon::Weapon(const WeaponXMLParser& wxp) : damage(wxp.getDamage())
{
}
Upvotes: 1
Reputation: 11
You could use const_cast and make a non-const reference to the const variable.
float &_damage = const_cast<float&>(damage);
_damage = 12.34;
Upvotes: 0
Reputation: 29754
you must do it in initializer list. And you can provide a function that will determine what damage is and returns it, so you can set your const variable:
class Weapon
{
public:
Weapon():damage(damage_xml()){}
const float damage;
private:
float damage_xml();
};
Upvotes: 0
Reputation: 1037
One approach is to use a "builder" class. So in your case you might have WeaponBuilder with appropriate methods that lets you do this:
WeaponBuilder wb(xmlFilename);
Weapon w(wb);
Then everything will be available in Weapon's constructor, so that you can make appropriate things const.
Upvotes: 0
Reputation: 180295
The body of the constructor indeed runs too late, your const
members already have a value. that comes from the initializer list :
Weapon::Weapon()
: damage(0.0f) // 0.0f is the default value
{
}
In your case, you'd have to get it from the XML file, e.g.
float Weapon::LoadDmgFromXML();
Weapon::Weapon()
: damage(LoadDmgFromXML())
{
}
Upvotes: 0
Reputation: 393934
Use an initializer-list:
#include "Weapon.h"
Weapon::Weapon() : damage(3.4)
{
}
Upvotes: 2