1

我有一个成员函数,它被声明为 const 并通过指针修改数据。这似乎具有误导性。我应该删除 const 关键字吗?

我想知道其他人如何在他们的代码中处理这种情况。人们是否只是添加评论以澄清发生了什么?他们不将 const 关键字添加到成员函数吗?也许完全是别的东西?

任何建议表示赞赏。

4

3 回答 3

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; }
};

这真的取决于你,也取决于你上课的目的。如果该类是智能指针,那么具有浅常量语义似乎是合理的,因为该类应该尽可能类似于原始指针(当然,您可以有一个指向非常量指针的常量原始指针)。

否则,您应该问自己为什么要公开对成员指针对象的访问权限。您当然有可能希望通过对您的类的持续引用来提供可变访问,但我想这些都是特殊和罕见的情况。首先,您的代码中不应该有那么多原始指针。通过取消引用一个指针来返回一个深度常量引用应该没问题,但通常在更好封装的“getter”函数中,它隐藏了你的类中有一个指针的事实,比如T const & get() const { return *ptr; }.

于 2012-09-13T16:41:23.237 回答
2

一般来说,是的。即使您可以做到,修改您声明为常量的内容也是一种欺骗性行为。

如果有人使用您的代码并看到 const,他们期望 const。修改,即使对你来说是明智的,也可能会给他们带来严重的问题——甚至使程序崩溃。

于 2012-09-13T16:37:12.473 回答
0

考虑一个std::vector<Blah>成员与Blah*用于实现动态数组的成员。大多数情况下,用前者代替后者是有意义的。对于Blah*成员const,允许方法修改数组中的数据,而对于std::vector<Blah>成员,const不允许方法修改那里的数据。

还要考虑一个带有索引方法的矩阵类,该方法返回允许分配给元素的代理。通过代理分配会改变矩阵,而不是代理对象本身。因此,代理对象的赋值运算符可以是(并且应该是)const,以便对其效果施加尽可能多的约束,而其主要工作是修改事物。

这是设计级别与编码级别不同的另一个示例。

在第一个示例中,使用成员数组,const所有关于表达设计级别约束,但在第二个示例中,使用分配代理,const所有关于表达编码级别约束。

然而,这些用法并非不兼容。关键思想是为代码的读者提供尽可能多的约束(因为这大大减少了理解或处理代码必须考虑的不同事物的数量)。结果:const在您实际可以添加的任何地方添加。

于 2012-09-13T17:15:46.733 回答