C++中常量成员函数的含义

本文深入探讨C++中常量成员函数的使用,如何合法地改变对象的逻辑状态而不改变其物理状态,以及如何通过mutable关键字解决懒惰评估机制带来的问题。同时,文章还介绍了函数重载解析如何区分常量和非常量版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文内容来源:《C++必知必会》

使用常量成员函数可以改变对象的逻辑状态,虽然对象的物理状态没有发生改变。考虑如下代码,它定义了一个类X:

class X{
public:
X():buffer_(
0),isComputed_(false){}
//...
void setBuffer(){
int *tmp = new int[MAX];
delete [] buffer_;
buffer_
= tmp;
}
//setBuffer

void modifyBuffer(int index, int value) const{
buffer_[index]
= value; //Valid but not suggested!
}//end of modifyBuffer

int getValue() const{
if( !isComputed_){
computedValue
= expensiveOperation(); //Error!
isComputed_ =true; // Error!
}
return computedValue_;
}
//end of getValue
private:
static int expensiveOperation();
int *buffer_;
bool isComputed_;
int computeValue_;
}

setBuffer函数必须是非常量的,因为它要修改其所属的X对象的一个数据成员。然而,modifyBuffer可以被合法地被标为常量,因为它没有修改X对象,它只是修改X的buffer_成员所指向的一些数据。这种做法是合法的,但是很不道德。

有时一个被声明为常量的成员函数必须要修改其对象,这常见于利用"lazy evaluation"机制来计算一个值时,换句话说,只有当第一次提出请求,才计算值,目的在于在该请求根本没有发出的其余情形下,让程序运行得更快。在这种情况下会有一个进行转型犯错的诱惑,为的是能够让事情变得更好,即将该成员函数声明为常量。

int getValue() const{
int (!isComputed_){
X
*const aThis = const_cast<X *const>(this);
aThis
->computedValue = expensiveOperation();
aThis
->isComputed_ = true;
}
return computedValue_;
}

千万抵制住这个诱惑!处理这种情形的正确方式是将有关数据成员声明为mutable:

class X{
public:
//...
int getValue() const{
int (!isComputed_){
computedValue
= expensiveOperation();
isComputed_
= true;
}
return computedValue_;
}
private:
mutable
bool isComputed_; //现在可以修改了。
mutable int computedValue_; //现在可以修改了。
}

类的非静态数据成员可以声明为mutable,这将允许它们的值可以被该类的常量成员函数(当然也包括非常量成员函数)修改,从而允许一个“逻辑上为常量”的成员函数被声明为常量,虽然其实现需要修改该对象。

以下例子可以解释函数重载解析是如何区分一个成员函数的常量和非常量版本的。

class X{
public:
//...
int &operator[] (int index);
cost
int &operator[](int index) const;
};

int i = 12;
X a;
a[
7] = i;// this 是 X *const,因为a是非常量
const X b;
i
= b[i]; // this 是 const X *const, 因为b 是常量

考虑如下具有两个常量参数的非成员二元操作符

X operator+(const X &, const X &);

如果决定声明一个与此重载操作符对应的成员形式的对应物,应该将其声明为常量成员函数,此目的是为了保持左实参的常量性质。

class X{
public:
//...
X operator+(const X &rightArg); // 左边的参数是非常量
X operator+(const X &rightArg) const; //左边的参数是常量
};

转载于:https://www.cnblogs.com/cmleung/archive/2011/05/24/2055060.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值