我查看了下面的代码类型,虽然我对问题 (*) 有个人答案,但我想听听 C++/设计专家的意见。
出于某种原因,Data
是一个具有不可修改标识符和可修改值的对象:
class Data
{
const Id m_id ; // <== note that m_id is a const member variable
Value m_value ;
Data(const Id & id, const Value & value) ;
Data(const Data & data) ;
Data & operator = (const Data & data) ;
// etc.
} ;
设计选择变成了语言选择,因为标识符是const
在类级别 (**) 声明的,以避免其(意外)修改,即使是从类成员函数内部...
...但是如您所见,有一个复制赋值运算符,其实现为:
Data & Data::operator = (const Data & that)
{
if(this != &that)
{
const_cast<Id &>(this->m_id) = that.m_id ;
this->m_value = that->m_value ;
}
return *this ;
}
复制赋值运算符不是 const 限定的事实使此代码安全(用户只能在非 const 对象上合法地调用此方法而不会引发未定义的行为)。
但是const_cast
,在 C++ 中使用修改其他 const 成员变量是一个不错的类设计选择吗?
我想强调以下几点:
- 数据显然是一个值类型(它有一个
operator =
成员函数) - 在这种模式中,其他一些函数也可能合法地需要
const_cast
(例如,移动构造函数/赋值和/或交换函数),但不是很多。
请注意,这可能是一个代码审查问题,但这不是“日常”代码。这是一个通用的 C++ 类型设计问题,需要平衡语言的需求/功能和模式/习语的代码解释。
还要注意,这mutable
(如在 C++98 中)不是问题的解决方案,因为其目的是使成员变量尽可能地不可修改。当然,mutable
(如在 C++11 中,Herb Sutter 的“你不知道const
和mutable
”)更不是一个解决方案。
(*) 我可以私下将我对该问题的回答转发给任何提问的人。
(**) 另一种解决方案是使对象非 const,并在接口级别使其成为 const(即不提供可以更改它的函数)