ProgrammerGuy123
ProgrammerGuy123

Reputation: 357

Assign to constant variable in a constructor?

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

Answers (6)

billz
billz

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

plonk
plonk

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

4pie0
4pie0

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

huskerchad
huskerchad

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

MSalters
MSalters

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

sehe
sehe

Reputation: 393934

Use an initializer-list:

#include "Weapon.h"
Weapon::Weapon() : damage(3.4)
{
}

Upvotes: 2

Related Questions