覆盖const函数来修改C ++中的类变量?

时间:2013-12-11 14:50:30

标签: c++

在编写我在空闲时间开发的个人软件时,我经常感到需要C ++中的功能,因此只能保护函数中的特定类变量不被修改。

编辑:以下示例说明具体用例不正确。请参考问题底部的EDIT部分。保持代码与现有答案保持一致。

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函数中的类变量。我该怎么办   是什么?

4 个答案:

答案 0 :(得分:5)

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

然后getArea()只需要return area;即可const

这种职责分离(设置者维护类不变量,getter只返回内部状态)是getter和setter的目的。

修改:另请注意,在此示例中,您并不需要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。如果修改变量不会改变类的向外含义,这将非常有用。它对于延迟初始化或维护内部统计信息非常有用。

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

答案 1 :(得分:2)

您可以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;
}

答案 2 :(得分:1)

  

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

是的,它是,你不应该。

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

const规则试图告诉你这个。

答案 3 :(得分:0)

正如其他人所指出的那样,你不应该存储area。决定您所谈论的圈子的仅仅是radius

如果您将area声明为成员,那么您将失去以下内容:

  • getter函数中的const限定符,如您所述。
  • CPU< - >内存IO,因为当您尝试读取区域时,系统地尝试更新对象数据中的区域。内存访问需要EONS。在每次访问时重新计算区域比从内存中获取区域要快得多。
  • 内存布局紧凑。如果您将结构放在vector中,则无意中将存储需求加倍,无法将对象加载到单个缓存行中。

我知道您的Circle课程确实是说明性的,但请尝试将这种思维方式转换为您的项目。