【问题标题】:Assign to constant variable in a constructor?在构造函数中分配给常量变量?
【发布时间】:2013-04-28 23:36:34
【问题描述】:

在 C++ 中,如何使变量成为常量,但在构造函数中分配给它?我想这样做的原因是因为我试图通过将所有数据放入 XML 文件然后将该数据加载到变量中来使用数据驱动设计。问题是我无法在初始化列表中加载值,所以我必须在构造函数(或其他地方)中加载,但变量不是常量。

这是一个 XML 文件:

<weapons>
    <pistol>
        <damage>5.0</damage>
        ...
    </pistol>
    ...
</weapons>

然后我有一个像这样的类:

标题

class Weapon
{
public:
    Weapon();
    const float damage;
};

来源

#include "Weapon.h"
Weapon::Weapon()
{
    //load damage value into damage variable
}

因为损坏变量是常量,所以我不能在构造函数中对它做任何事情,只能在初始化列表中,但显然我不能像在初始化列表中读取 XML 文件那样执行代码。因此,即使变量永远不会改变,我应该不让它保持不变还是有适当的方法让它保持不变并做我需要的事情?

【问题讨论】:

  • 为什么不能在初始化列表中执行这样的代码?只需编写一个独立的函数(最好在 Weapon.cpp 中的匿名命名空间中),它会解析出伤害值并返回它。然后您可以在初始化损坏变量时在初始化器列表中调用该函数。哦,请把它设为私有。
  • 是的,我什至没有考虑过查看我对已接受答案的评论。是的,我会将其设为私有。

标签: c++ initialization constants


【解决方案1】:

使用初始化列表:

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

【讨论】:

  • 问题的字面意思是“问题是我无法加载初始化列表中的值”。这缺少初始化表达式是执行加载的函数调用的位,而不仅仅是编译时常量。
【解决方案2】:

你可以有一个 xml 解析器,例如:

class WeaponXMLParser
{
public:
   WeaponXMLParser(const std::string& filename);
   float getDamage();
};

在初始化列表中初始化 const 成员:

Weapon::Weapon(const WeaponXMLParser& wxp) : damage(wxp.getDamage())
{
}

【讨论】:

  • 没想到我可以调用函数来返回初始化器列表中的值。当我说“显然我不能像在初始化列表中读取 XML 文件那样执行代码”时,我猜我错了。
【解决方案3】:

构造函数的主体确实运行得太晚了,您的const 成员已经有了值。来自初始化列表

Weapon::Weapon()
  :  damage(0.0f) // 0.0f is the default value
{
}

在您的情况下,您必须从 XML 文件中获取它,例如

float Weapon::LoadDmgFromXML();
Weapon::Weapon()
      :  damage(LoadDmgFromXML())
{
}

【讨论】:

  • 仍然值初始化,8.5/7 说“(可能是 cv-qualified)”,即 cv 资格没有区别。而这反过来意味着对非类非数组类型进行零初始化,这最终意味着 0(零),作为一个整数常量表达式,转换为浮点数。但这不适合评论。
【解决方案4】:

一种方法是使用“builder”类。因此,在您的情况下,您可能会使用带有适当方法的 WeaponBuilder 来执行此操作:

WeaponBuilder wb(xmlFilename);
Weapon w(wb);

然后,Weapon 的构造函数中的所有内容都将可用,以便您可以将适当的东西设为 const。

【讨论】:

    【解决方案5】:

    您必须在初始化列表中执行此操作。您可以提供一个函数来确定损坏是什么并返回它,因此您可以设置 const 变量:

    class Weapon
    {
    public:
        Weapon():damage(damage_xml()){}
        const float damage;
    private:
        float damage_xml();
    };
    

    【讨论】:

      【解决方案6】:

      您可以使用 const_cast 并对 const 变量进行非常量引用。

      float &_damage = const_cast<float&>(damage);
      _damage = 12.34;
      

      【讨论】:

      • 这是未定义的行为。 -1
      • 让你的程序崩溃并烧毁。