矢量和[] - 运算符重载

use*_*330 2 c++ vector operator-overloading

我从std :: vector继承了我的类.现在我想重载[] -operator.
当我尝试为我的向量分配一个新值时,例如v[0]=5,我应该收到该消息OK.

这是我的代码(我知道,这没有意义,我只是玩耍):

#include<vector>
#include<iostream>
class Vec : public std::vector<int> {
public:
    int operator[](int);
};

int Vec::operator[](int i) {
    (*this)[i] = i;
    std::cout << "OK";
    return 123;
}

int main() {
    Vec v;
    v[0]=5;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是我收到以下错误:

In member function ‘int Vec::operator[](int)’:
error: lvalue required as left operand of assignmen
In function ‘int main()’:
error: lvalue required as left operand of assignment
Run Code Online (Sandbox Code Playgroud)

pax*_*blo 6

导致此特定错误的原因是您没有返回lvalue,通常定义为可以出现在赋值左侧的内容,例如v[0] = 5;.您在其他答案中指出了更多问题,但这是您遇到的错误消息(a)的具体问题.

重载索引运算符的正确规范是:

int& operator[] (const int nIndex);
Run Code Online (Sandbox Code Playgroud)

如果要将其视为一个项目,则必须返回对该项目的引用(以便可以对其进行修改)lvalue.下面的代码显示了一个修复程序,尽管在这个简化的情况下显然所有数组索引都映射到相同的值:

#include <vector>
#include <iostream>

class Vec : public std::vector<int> {
    public:
        int& operator[] (int);    // <-- note the '&'
    private:
        int xyzzy;
};

int& Vec::operator[] (int idx) {  // <-- note the '&'
    std::cout << "OK\n";
    return xyzzy;
}

int main () {
    Vec v;
    v[0] = 5;
    v[1] = 6;
    std::cout << v[22] << '\n';
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个输出是:

OK
OK
OK
6
Run Code Online (Sandbox Code Playgroud)

实际上,您不会将所有索引映射到相同的值,上面的代码只是为了说明正确的函数签名.我没有打算给出一个更完整的例子,因为使用非虚拟析构函数对类进行子类化通常会导致非平凡代码中的问题(b).


(a)std::vector由于析构函数不是虚拟的,因此通常不认为是子类的好主意,因此在尝试以多态方式销毁对象时可能会遇到麻烦.

你可能最好使用一个has-a关系(你的类包含一个向量)而不是一个is-a关系(你继承的地方).

遗憾的是,您可能需要从类中创建大量的传递方法到底层向量(尽管只有您需要的那些),但它将解决析构函数的问题.


(b)(a) :-)


Luc*_*ore 5

您需要返回对元素的引用-但是请注意,即使您这样做了,也会遇到无限递归-您的operator[]调用本身。

无论哪种方式-继承std::vector都不是一个好主意。请改用合成。

  • @ user1170330我没有那么说。您可以使用`int&operator [](int idx){return std :: vector &lt;int&gt; :: operator [](idx); }`。只是不推荐。 (2认同)