重写 const 函数以修改 C++ 中的类变量

Override const function to modify a class variable in C++?

本文关键字:类变量 C++ 修改 const 函数 重写      更新时间:2023-10-16

在编写我在空闲时间开发的个人软件时,我经常觉得需要C++功能,以便只有函数中的特定类变量必须被保护不被修改。

编辑:以下示例不正确,无法解释特定的用例。请参考问题底部的"编辑"部分。保持代码只是为了与现有答案保持一致。

class Circle
{
  private:
    double radius;
    double area;
  public:
    void setRadius(double r);
    double getArea();
};
void Circle::setRadius(double r)
{
    radius = r;
}
double Circle::getArea()
{
    area = 3.142 * radius * radius;
    return area;
}

这是一个非常简单的例子,只是为了解释这个问题。现在在getArea()我想防止修改radius.但是我无法使getArea() const功能,因为area在其中进行了修改。

有些人可能会说这是我愚蠢的编程,但有时我发现自己处于这种情况。这将真正有助于防止开发阶段本身的错误。如果C++没有办法做到这一点,那么请提供您宝贵的建议来解决这种情况。

编辑:在这个例子中,getArea()所涉及的计算非常少,因为它只依赖于radius,但有时它可能取决于许多变量。如果在获取area之前需要修改所有变量,则每个变量的 setter 函数中的计算区域将导致不必要的计算。计算area的值可能是计算密集型的,因此将结果值存储为类变量是避免在多次调用 area 的 getter 时重新计算的好方法。在这种情况下,以下问题是有效的:

我需要修改 const 函数中的类变量。我该怎么做 那?

你应该在setRadius()内部计算area,因为arearadius之间的关系是固定的,并且是一个类不变量。

然后getArea()只需要return area;就可以const.

这种职责分离(二传手保持类不变性,二传手只是返回内部状态(是获取者和二传手的目的。

编辑:另请注意,在此示例中,您不需要area成为类的成员。 您可以按如下方式定义类:

class Circle
{
  private:
    double radius;
  public:
    void setRadius(double r);
    double getArea() const;
};
void Circle::setRadius(double r)
{
    radius = r;
}
double Circle::getArea() const
{
    double area = 3.142 * radius * radius;
    return area;
}

通过使area成为方法的局部变量而不是类成员,该方法可以保持const

正如其他人所指出的,还有一个mutable关键字,您可以将其应用于 area 。 如果修改变量不会更改类的外部含义,这将非常有用。 它可用于延迟初始化或维护内部统计信息。

但是,通常情况下,如果预先维护类的属性和不变量,则更容易推理它们。

你可以area做一个mutable,并标记getArea() const

mutable double area;
double Circle::getArea() const 
{
    area = 3.142 * radius * radius;
    return area;
}
这是数据成员

延迟初始化的常见习惯用法,通常在所述数据成员的构造成本很高时使用。

在这种情况下,根本不清楚缓存area是否有好处。您可以通过删除area数据成员并返回结果来回避此问题

double Circle::getArea() const 
{
    return 3.142 * radius * radius;
}

有些人可能会说这是我愚蠢的编程,但有时我发现自己处于这种情况。

是的,是的,你不应该。

如果您发现必须缓存此类计算,请在计算组件因子时而不是在 getter 中执行此操作。(坦率地说,在这种情况下,我根本不会存储area

const规则试图告诉你这一点。

正如其他人指出的那样,您不应该存储area。决定你在说什么圈子的只是radius.

如果您将area声明为会员,您将失去以下损失:

  • 正如您所指出的,您的 getter 函数上的const限定符。
  • CPU <>内存 IO,因为每当尝试读取区域时,您都会系统地尝试更新对象数据中的区域。内存访问采用 EONS。在每次访问时重新计算面积确实比从内存中获取面积要快得多。
  • 内存布局的紧凑性。如果您将结构放在vector中,您将无用地将存储需求加倍,失去将两倍的对象加载到单个缓存行中的机会。

我知道你的Circle课真的很说明问题,但试着把这种思维方式应用到你的项目中。