在我在网上找到的以下示例中,提到const_cast
的一个优点是它允许常量函数更改类成员。这是一个问题。我们为什么要按const
为函数设置规则,然后使用const_cast
破坏该规则?这不是作弊吗?最好不要为函数设置const
吗?
#include <iostream>
using namespace std;
class student
{
private:
int roll;
public:
student(int r):roll(r) {}
// A const function that changes roll with the help of const_cast
void fun() const
{
( const_cast <student*> (this) )->roll = 5;
}
int getRoll() { return roll; }
};
int main(void)
{
student s(3);
cout << "Old roll number: " << s.getRoll() << endl;
s.fun();
cout << "New roll number: " << s.getRoll() << endl;
return 0;
}
答案 0 :(得分:5)
这确实是一个坏主意。除了说明函数的行为之外,它还允许您修改常量student
对象的成员,从而给出未定义的行为。
通常,成员函数应为const
,并且仅当它不修改对象的可观察状态时才应该const
。所以在这种情况下,它不应该是mutable
。
有时,您可能希望特定成员可以在不会导致可观察到的变化的函数中进行修改;例如,锁定互斥锁以访问共享数据,或缓存复杂计算的结果。在这种情况下,声明这些成员const
,以便该类的其余部分仍受{{1}}保护 - 正确性。
答案 1 :(得分:1)
这是const_cast
用法的一个不好的例子。想象一个更好的例子。发布的类的方法未被错误地声明为const
。你有一个这个类的const引用,想要调用这个方法。但你不能这样做,因为它没有被错误地声明为const
。在这种情况下,你可以对编译器说:“好吧,我知道我在做什么,我知道这个方法实际上并没有改变任何东西,只是从该引用中删除const-ness并允许我调用这个方法。相信我,我是一名程序员“。
现实生活中的例子。在OpenCV库中,没有不可变图像这样的东西。核心类cv::Mat
是可变的。假设您要在常量内存缓冲区周围创建只读包装器。你可以构造它的唯一方法是通过强制转换const,如下所示:
const char* myConstBuffer = GetConstBuffer();
const cv::Mat myConstImage(const_cast<char*>(myConstBuffer), /* dimensions, etc. */);
这是一个合法代码,因为构造的图像具有类型const cv::Mat
,您无法在其上调用任何修改方法。但是在这里使用const_cast
仍然会发现一个设计错误:应该有一种有效的方法来构造这样的只读缓冲区。
答案 2 :(得分:0)
const
主要是向呼叫者表达意图。当成员函数标记为const
时,您告诉调用者他们可以预期此对象的公共接口不会更改。
但是想象一下您希望使用序列号记录对此函数的调用的方案。该序列号需要更改,但此更改仅在类的私有深度内可见。在这种情况下,对于&#34;作弊&#34; const我将序列号变量标记为mutable
。
const_cast
是类似的理由。
答案 3 :(得分:0)
明亮的例子 - 引用计数对象。事实上,引用计数声明对象的生命周期政策,但并不涉及真实的&#34;业务&#34;类实现的流程。虽然const
与业务流程有关。例如 - 您有商业帐户,但无法更改它:
class BusinessAccount{
unsigned _refcount;
double _amount
...
你有一些操作&#34;查看&#34;
void view(SmartPtr<BusinessAccount> smart_ptr)
因此,如果view
必须取得对象的所有权 - 它必须增加_refcount。
PS 更好的解决方案关键字 - mutable
on field _refcount而不是const_cast