我在类operator[]
中定义了两个版本的重载array
函数。 ptr
是指向array
对象的第一个元素的指针。
int& array::operator[] (int sub) {
return ptr[sub];
}
和
int array::operator[] (int sub) const {
return ptr[sub];
}
现在,如果我定义一个const对象integer1
,那么第二个函数只能被调用.....但是如果我创建一个非const对象然后调用如下:
cout << "3rd value is" << integer1[2];
这里调用哪个函数?
答案 0 :(得分:2)
你的const版本应该返回const int&
而不是int
,因此两个函数之间的语义只是。
完成后,无关紧要使用哪一个。如果必须使用const
版本,因为你的对象有一个const上下文,那么它将是...并且它并不重要,因为你没有尝试修改任何东西。否则,它将使用非const
版本......但效果相同。
答案 1 :(得分:2)
在第二个示例中,将调用非const版本,因为不需要转换,并且不需要转换的调用比需要转换的调用更好。
但是,最终,你有一个基本的问题:你真正想要的是根据你是将你的对象用作右值还是左值来改变的行为,而const
并不是真的那么做。为了使其正常工作,您通常希望返回代理对象,并为代理对象重载operator=
和operator T
:
template <class T>
class myarray {
T *ptr;
class proxy {
T &val;
proxy &operator=(proxy const &p); // assignment not allowed.
public:
proxy(T &t) : val(t) {}
operator T() const { return val; }
proxy &operator=(T const&t) { val = t; return *this; }
};
proxy const operator[](int sub) const { return proxy(ptr[sub]); }
proxy operator[](int sub) { return proxy(ptr[sub]); }
// obviously other stuff like ctors needed.
};
现在我们得到了理智的行为 - 当我们的array<int>
(或任何类型)是const时,我们将使用operator[] const
,并且它会给出const proxy
。由于它的赋值运算符不是 const,因此尝试使用它们将失败(不会编译)。
OTOH,如果原始array<int>
不是const,我们将获得非const代理,在这种情况下,我们可以同时使用operator T
和operator=
,并且能够读取和写入array<int>
中的值。