const_cast 为函数 const 设置规则并打破它
const_cast setting a rule and breaking it for function const
在我在网上找到的以下示例中,提到const_cast
的优点之一是它允许常量函数更改class 成员。这对我来说是个问题。为什么我们应该通过 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;
}
const
主要是向来电者表达意图。当一个成员函数被标记为 const
时,您是在告诉 调用者 他们可以期待此函数的 public 接口 对象不改变。
但想象一下您想要使用序列号记录对该函数的调用的场景。该序列号需要更改,但此更改仅在 class 的私人深处可见。在这种情况下 "cheat" const my 将序列号变量标记为 mutable
.
是合适的
const_cast
也是类似的道理。
这确实是个坏主意。除了对函数的行为撒谎外,它还允许您修改常量 student
对象的成员,从而给出未定义的行为。
一般来说,当且仅当它不修改对象的可观察状态时,成员函数才应该是 const
。所以在这种情况下,它不应该是 const
.
有时,您可能希望特定成员在函数中可以修改,否则不会导致可观察到的变化;例如,锁定互斥量以访问共享数据,或缓存复杂计算的结果。在那种情况下,声明那些成员 mutable
,以便 class 的其余部分仍然受到 const
-正确性的保护。
这是 const_cast
用法的糟糕示例。想象一个更好的例子。已发布的 class 的方法未被错误地声明为 const
。您有一个对此 class 的常量引用并希望调用此方法。但是你不能这样做,因为它没有被错误地声明为const
。在这种情况下,您可以对编译器说:"Ok, I know what I'm doing, I know this method does not actually change anything, just remove const-ness from that reference and allow me to call this method. Trust me, I'm a programmer".
现实生活中的例子。在 OpenCV 库中,没有不可变图像这样的东西。核心 class cv::Mat
是可变的。假设您想围绕一个常量内存缓冲区创建一个只读包装器。构造它的唯一方法是强制转换 const,如下所示:
const char* myConstBuffer = GetConstBuffer();
const cv::Mat myConstImage(const_cast<char*>(myConstBuffer), /* dimensions, etc. */);
这是一个合法的代码,因为构造图像的类型是const cv::Mat
,你不能在它上面调用任何修改方法。但是这里使用const_cast
仍然暴露了一个设计错误:应该有一个有效的方法来构造这样的只读缓冲区。
最好的例子——引用计数对象。事实上,引用计数声明了对象生命周期策略,但与 class 实现的真实 "business" 流程无关。而 const
与业务流程有关。例如 - 您有企业帐户,但无法更改它:
class BusinessAccount{
unsigned _refcount;
double _amount
...
你有一些操作要"view"
void view(SmartPtr<BusinessAccount> smart_ptr)
因此,如果 view
必须取得对象的所有权 - 它必须增加 _refcount。
PS 关键字的更好解决方案 - mutable
在字段 _refcount 而不是 const_cast
在我在网上找到的以下示例中,提到const_cast
的优点之一是它允许常量函数更改class 成员。这对我来说是个问题。为什么我们应该通过 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;
}
const
主要是向来电者表达意图。当一个成员函数被标记为 const
时,您是在告诉 调用者 他们可以期待此函数的 public 接口 对象不改变。
但想象一下您想要使用序列号记录对该函数的调用的场景。该序列号需要更改,但此更改仅在 class 的私人深处可见。在这种情况下 "cheat" const my 将序列号变量标记为 mutable
.
const_cast
也是类似的道理。
这确实是个坏主意。除了对函数的行为撒谎外,它还允许您修改常量 student
对象的成员,从而给出未定义的行为。
一般来说,当且仅当它不修改对象的可观察状态时,成员函数才应该是 const
。所以在这种情况下,它不应该是 const
.
有时,您可能希望特定成员在函数中可以修改,否则不会导致可观察到的变化;例如,锁定互斥量以访问共享数据,或缓存复杂计算的结果。在那种情况下,声明那些成员 mutable
,以便 class 的其余部分仍然受到 const
-正确性的保护。
这是 const_cast
用法的糟糕示例。想象一个更好的例子。已发布的 class 的方法未被错误地声明为 const
。您有一个对此 class 的常量引用并希望调用此方法。但是你不能这样做,因为它没有被错误地声明为const
。在这种情况下,您可以对编译器说:"Ok, I know what I'm doing, I know this method does not actually change anything, just remove const-ness from that reference and allow me to call this method. Trust me, I'm a programmer".
现实生活中的例子。在 OpenCV 库中,没有不可变图像这样的东西。核心 class cv::Mat
是可变的。假设您想围绕一个常量内存缓冲区创建一个只读包装器。构造它的唯一方法是强制转换 const,如下所示:
const char* myConstBuffer = GetConstBuffer();
const cv::Mat myConstImage(const_cast<char*>(myConstBuffer), /* dimensions, etc. */);
这是一个合法的代码,因为构造图像的类型是const cv::Mat
,你不能在它上面调用任何修改方法。但是这里使用const_cast
仍然暴露了一个设计错误:应该有一个有效的方法来构造这样的只读缓冲区。
最好的例子——引用计数对象。事实上,引用计数声明了对象生命周期策略,但与 class 实现的真实 "business" 流程无关。而 const
与业务流程有关。例如 - 您有企业帐户,但无法更改它:
class BusinessAccount{
unsigned _refcount;
double _amount
...
你有一些操作要"view"
void view(SmartPtr<BusinessAccount> smart_ptr)
因此,如果 view
必须取得对象的所有权 - 它必须增加 _refcount。
PS 关键字的更好解决方案 - mutable
在字段 _refcount 而不是 const_cast