【问题标题】:Usage of const data member in C++C++中const数据成员的使用
【发布时间】:2016-05-09 10:35:27
【问题描述】:

嗯,我知道 C++ 类中 const 数据成员的功能。

我想知道的是,在类中引入 const 数据成员的目的。为什么有人会在编写真正的软件时使用它? const 数据成员的实际用途是什么?

请给我一些现实生活中的例子并说明原因。

编辑: 我不是在问static const 数据成员。 我正在询问一些现实生活中的用例,其中每个对象对于相同的数据将具有不同的 const 值。

【问题讨论】:

  • 对于在构造时确定的类不变量?
  • constexpr static double pi = 3.14....
  • @paper.plane 当你需要一个不是 const 的数据成员时,你能给我一个具体的例子吗?我会说 const 是默认情况下,而不是 const 是例外
  • @AlessandroTeruzzi:您计划存储在标准容器中的任何对象,仅此而已。我原则上同意你的观点,我在我的代码中洒满了const,但是让封装类不可赋值是一个很大的限制。此外,还有几乎无限的潜在有用类,它们的状态会随着时间而变化。
  • @LightnessRacesinOrbit 我正在用我的评论推动信封。在我的辩护中,我发现软件社区确实偏向于可变对象(恕我直言,它们的缺点被广泛低估了)。但是,我同意,设计一个限制其接口的不可变对象比将数据成员设置为 const 更容易、更方便。

标签: c++ use-case


【解决方案1】:

您使用 const 数据成员的原因与您使用 any const 对象的原因相同:对于可以任意初始化但永远不会更改的值。 p>

一个好的经验法则是将const“默认”表示为“默认”,这样您就可以想出很多在课堂上使用它的理由。

class User
{
    User(const std::string& name)
      : name(name)
    {}

private:
    /**
     * User's name is an invariant for the lifetime of this object.
     */
    const std::string name;
};

你能把const 去掉吗?当然可以。但是,当您无意更改时,您可能会意外更改nameconst 的全部目的是防止此类事故发生。

但是,遗憾的是,您的课程将无法分配!

【讨论】:

  • 是的,这是一个很好的例子。因此,每当您需要更正您的银行记录中错误提及的姓名时,您可以调用客户服务,然后在构造函数中创建另一个具有正确名称的对象,并使用旧对象调用赋值运算符,然后删除旧对象对象。
  • @paper.plane:好吧,如果更改名称在您的业务逻辑中合法且有效,那么您将不会使用const。不过,“客户编号”可能必须是 const
  • 我同意你的观点@Lightness,但我只是想知道在需要更改时实施是否正确,考虑到允许更改名称。
  • @paper.plane:我没有关注。
【解决方案2】:

有几种情况。最明显的一个是静态 const 数据成员。这些用作作用域常量:

class Something {
  static const int SOME_CONSTANT = 17;
};

请注意,在 C++11 及更高版本下,constexpr 在这些情况下通常更有意义。

这定义了一个常量,该常量是类型化的并限定于类的实现。但是,我怀疑这不是您要问的。

更有趣的用例是类的实例之间的值不同,但在类的生命周期内保持不变。

例如,假设您有一个 RAID 实施,其中配置设置条带宽度。您在编译时不知道条带宽度,因此上述构造对您没有帮助。但是,您确实希望宽度在整个类的生命周期内保持不变(也许您的代码不知道如何处理条带宽度的变化)。

在这些情况下,将值标记为 const 并将其设置在构造函数中,可以在编译时保证没有人更改此值。

【讨论】:

  • 你的逻辑有点问题。即使是static constexpr,类的实例之间也可能有所不同,即如果它是从模板参数初始化的。此外,我们希望看到static const 的任何地方都是static constexpr(constexpr 意味着 const)。公共const variable 也没有理由不成为static constexpr
  • 我不认为一个类的不同实例是“同一个类”(编译器也不认为)。至于第二条评论,有时您需要一个只能在运行时计算的“全局”常量(例如内存总量)。我同意 constexpr 通常是有道理的,并且会修改答案
【解决方案3】:

您使用它与使用全局声明的 const 完全相同,只是您希望它仅适用于您定义它的类。例如

class Character
{
public:
    Character()
    :
        mCurrentHealth{TOTAL_HEALTH},
        mCurrentMana{TOTAL_MANA}
    {
    }

    // Define lose/gain health/mana functions
    // for mCurrentHealth and mCurrentMana
private:
    int mCurrentHealth;
    int mCurrentMana;

    // Constants
    const int TOTAL_HEALTH = 100;
    const int TOTAL_MANA = 50;
};

还有很多其他示例,但重点是我们不希望在类之外定义 TOTAL_HEALTH 和 TOTAL_MANA,因为它们不相关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 2014-03-19
    • 2011-06-04
    • 2021-09-11
    相关资源
    最近更新 更多