const 表示你承诺不会改变变量。还是可以改的。
class A {
public:
A(const int& a);
int getValue() const;
void setValue(int b);
private:
const int& a;
};
A::A(a) : a(a) {}
int A::getValue() const {
return a;
}
void A::setValue(int b) {
a = b; // error
}
int main() {
int my_a = 0;
A a(my_a);
std::cout << a.getValue() << std::endl; // prints 0
my_a = 42;
std::cout << a.getValue() << std::endl; // prints 42
}
没有方法A::* 可以改变a,但main 可以。这在 C 和 C++ 之间是相同的。
C++ 确实有几种(有限的)绕过const 的方法,它们应该阻止程序员不恰当地丢弃const。
参加这样的课程。
class A {
public:
A();
int getValue();
private:
static int expensiveComputation();
int cachedComputation;
};
A::A() : cachedComputation(0) {}
A::getValue() {
if (cachedComputation == 0)
cachedComputation = expensiveComputation();
return cachedComputation;
}
cachedComputation 隐含地表示this->cachedComputation。请记住这一点。
int main() {
A a1;
const A a2;
std::cout << a1.getValue() << std::endl;
std::cout << a2.getValue() << std::endl; // error
}
a2.getValue() 是非法的,因为在 const A a2 上调用了非const 方法。可以抛弃const-ness……
std::cout << ((A&)a2).getValue() << std::endl; // C-style cast
std::cout << const_cast<A&>(a2).getValue() << std::endl; // C++-style cast
第二个是首选,因为编译器将检查只有const-ness 被强制转换,没有别的。然而,这仍然不理想。相反,应该在类中添加一个新方法。
class A {
public:
int getValue() const;
};
A::getValue() const {
if (cachedComputation == 0)
cachedComputation = expensiveComputation(); // error
return cachedComputation;
}
现在有一个const 方法,所以a2.getValue() 没问题。但是,结尾的 const 意味着该方法被赋予了一个 const A *this 指针,而不是像往常一样的 A *this 指针,这使得 this->cachedComputation 成为一个不能被变异的 const int &。
const_cast 可以应用在方法内部,但最好更改此成员的声明。
class A {
private:
mutable int cachedComputation;
};
现在,即使使用 const A *this,this->cachedComputation 也可以在不强制转换的情况下进行变异。