最近我在const-correctness上阅读this faq。现在我遇到了以下情况,我不知道该怎么做const或mutable。 假设一个简单的例子:
class Averager {
public:
Averager() : sum(0),isUptoDate(false),N(0){}
void add(double x){
sum+=x;
N+=1;
isUptoDate = false;
}
double getAverage() const {
if (!isUptoDate){updateAverage();}
return average;
}
private:
void updateAverage(){
if(N>0){average = sum / N;}
else {average = 0;}
isUptoDate = true;
}
double sum;
mutable bool isUptoDate;
int N;
double average;
};
在实际情况中,updateAverage()
是一项昂贵的计算,因此我希望每次添加值时都不要更新。此外,在添加新值之前,可能会多次调用getAverage()
,因此我只想在真正需要时才更新。另一方面,类的用户不应该负责调用updateAverage()
,因此我使用该标志来知道是否必须进行更新。
据我了解,getAverage()
显然应该是const方法,而isUptoDate
可以是可变的(它不是逻辑状态的一部分,而只是私有实现细节)。但是,updateAverage()
绝对不是const,我不能在const方法中调用它。
我的做法出了什么问题?
答案 0 :(得分:3)
我看起来很好,你只需要使你的average
也变得可变,因为它会被getAverage
懒惰地计算出来。 updateAverage
也应为const
,因为它将由getAverage
调用。由于updateAverage
是私有的,因此它自己的存在是一个实现细节。它只被调用一次,您也可以将其内联到getAverage
:
double getAverage() const {
if (!isUptoDate){
if(N>0){average = sum / N;}
else {average = 0;}
isUptoDate = true;
}
return average;
}
确实,我真的建议你内联它,因为将它放在头文件中是没有意义的(如果你改变它的签名或它的常量,你必须重新编译所有用户) 。如果它不仅仅是真实案例中的3行,你可以将它作为lambda,如果你使用C ++ 11:
double getAverage() const {
auto updateAverage=[&]{
if(N>0){average = sum / N;}
else {average = 0;}
isUptoDate = true;
};
if (!isUptoDate){ updateAverage(); }
return average;
}