常量和非常量运算符重载

40

我有一个话题不太清楚,需要更详细的解释。它涉及到带有const版本和非const版本的运算符重载。

// non-const
double &operator[](int idx) {
    if (idx < length && idx >= 0) {
        return data[idx];
    }
    throw BoundsError();
}

我理解这个lambda函数会接收一个索引并检查其有效性,然后返回类中数组数据的索引。还有一个具有相同代码体的函数,但函数调用不同。

const double &operator[](int idx) const

为什么我们需要两个版本?

例如,在下面的示例代码中,每个实例中使用了哪个版本?

Array a(3);
a[0] = 2.0;
a[1] = 3.3;
a[2] = a[0] + a[1];

我假设 const 版本只会被调用在 a[2] 上,因为我们不想冒险修改 a[0] 或者 a[1]

谢谢任何帮助。


2
你可以轻松地检查哪个被调用,并在其中输出。 - chris
这是一张讲座幻灯片,我希望不必创建一个类来利用它们,而只需要有人帮助我理解为什么我们要这样做。 - James Wilks
6
不要懒惰,亲身尝试一下,这样可以更好地记住。 - Jonathan Wakely
我的假设是,只有在a[2]上调用const版本,因为我们不想冒险修改a[0]a[1]。这毫无意义,操作a[2]a[0]a[1]无关,它涉及到的是a和整数字面量2 - Jonathan Wakely
我发现这个视频很有帮助:https://www.youtube.com/watch?v=4fJBrditnJU。直接跳到8:15。 - Sabito stands with Ukraine
3个回答

44
当两个版本都可用时,逻辑非常简单:对于const对象调用const版本,对于非const对象调用非const版本。就是这样。
在您的代码示例中,a是一个非const对象,这意味着在所有情况下都调用非const版本。在您的示例中,永远不会调用const版本。
有两个版本的目的是为了实现对非const对象的“读/写”访问以及仅对const对象的“读”访问。对于const对象,调用operator []的const版本,该版本返回const double &引用。您可以通过该const引用读取数据,但不能通过它进行写入。

我不知道——我发现很难调用非const版本。请查看此实时演示:http://coliru.stacked-crooked.com/a/1c820d80113bc9e3 - Reb.Cabin
1
@Reb.Cabin:在你的演示中,你从未尝试调用operator[]的非const版本。每次你有这样的机会,你都使用this->elems[i]。请注意,this->elems是一个普通的原始指针。它的[]运算符是普通的内置索引器,而不是你重载的索引器。如果你想调用你重载的非const版本的operator [],你必须在赋值的左侧使用(*this)[i],而不是this->elems[i] - AnT stands with Russia
我明白了。我重写了构造函数,并提供了一个更好的例子来使用非const索引器。这是一个有帮助且阐明的注释。http://coliru.stacked-crooked.com/a/3a2e3960c1e77d78 - Reb.Cabin
在关系运算符重载的情况下,我们应该提供两个还是只提供一个就足够了?在这种情况下,我们应该使用哪一个?例如,bool operator<(const Type &t) const 或者 bool operator<(const Type &t) 哪一个更好? - kovac

6
为了补充上面的答案,提供一个代码示例:
Array a(3);
a[0] = 2.0;  //non-const version called on non-const 'a' object

const Array b(3);
double var = b[1];  //const version called on const 'b' object

const Array c(3);
c[0] = 2.0;  //compile error, cannot modify const object

0
我觉得如果有一个选项像这样的话
double k = 3.0;

数组的元素是常量。
a[0] = a[1] + k; or std::cout << a[0] + k;

将调用const double &operator[](int idx) const版本。在这里,您正在将非const变量添加到const对象中。


1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接