我有一个成员函数,它被声明为const并通过指针修改数据。这似乎有误导性。我应该删除const关键字吗?
我想知道其他人如何在他们的代码中处理这种情况。人们只是添加评论来澄清发生了什么吗?他们不是将const关键字添加到成员函数中吗?也许还有别的什么呢?
感谢任何建议。
答案 0 :(得分:3)
您基本上有两种选择:
深度常量:
class Foo
{
T * ptr;
public:
T & operator*() { return *ptr; }
T const & operator*() const { return *ptr; }
T * operator->() { return ptr; }
T const * operator->() const { return ptr; }
};
浅层常数:
class Foo
{
T * ptr;
public:
T & operator*() const { return *ptr; }
T * operator->() const { return ptr; }
};
这完全取决于你,以及你班级的目的。如果类是一个智能指针,那么使用浅的constness语义似乎是合理的,因为该类应该尽可能与原始指针相似(并且你当然可以有一个指向非常量指针的常量原始指针) )。
否则,您应该问自己为什么要公开对成员指针对象的访问权限。您当然可以通过对类的不断引用来提供可变访问,但我想这些是特殊且罕见的情况。首先,代码中应该没有那么多原始指针。通过解除引用指针返回一个深度const引用应该没问题,但通常是更好的封装“getter”函数,它隐藏了类中有一个指针的事实,如T const & get() const { return *ptr; }
。
答案 1 :(得分:2)
一般来说,是的。它具有欺骗性,可以修改你声明不变的东西,即使你可以做到这一点。
如果有人使用你的代码并看到const,他们会期望const。修改虽然对你很敏感,但可能会导致严重的问题 - 甚至会导致程序崩溃。
答案 2 :(得分:0)
考虑std::vector<Blah>
成员与用于实现动态数组的Blah*
成员。通常,用前者替换后者是有意义的。使用Blah*
memeber,允许const
方法修改数组中的数据,而使用std::vector<Blah>
成员时,const
方法不允许修改数据。< / p>
还要考虑一个带有索引方法的矩阵类,该方法返回一个允许赋值给元素的代理。通过代理分配更改矩阵,而不是代理对象本身。因此,代理对象的赋值运算符可以(并且应该是)const
,以便对其效果施加尽可能多的约束,而其主要工作是修改事物。
这是设计级别与编码级别不同的另一个例子。
在第一个示例中,使用成员数组,const
完全是关于表达设计级别约束,但在第二个示例中,使用赋值代理,const
完全是关于表达编码级别约束
然而,这些用法并非不相容。关键的想法是为代码的读者提供尽可能多的约束(因为这极大地减少了必须考虑理解或处理代码的不同事物的数量)。 Upshot:在任何地方添加const
。