方括号重载 => 没有运算符匹配操作数

Square brackets overloading => no operator matches operands

我目前在重载自定义向量中的方括号时遇到一些问题 class。

我的class基本上是这样的:

typedef uint32_t u32; // This is not actually here, but so you get the idea. Also, it is included in the problematic call's file

template<class T>
class JFFVector
{
public:
    //Init and stuff
    T& operator[](u32 iIndex)
    {
        return m_pData[iIndex + miDataOffset];
    }

private:
    T* m_pData;
    u32 m_iDataOffset;
}

在这个 classes 函数中,我可以调用 (*this)[0] 并且一切正常。 现在我遇到的问题是 class 的成员如下:

class TOtherClass
{
public:
    // Stuff
    void DoSomething() const
    {
        for (u32 i; i < m_tItems.size(); ++i)
            m_tItems[i]->DoStuff(); // Which is a const function
    }

private:
    JFFVector<const JFFItem*> m_tItems;
}

问题是我的编译器在我面前抛出一个错误说

no operator "[]" matches these operands

operand types are: const JFFVector[u32]

typedef uint32_t u32.

所以我注意到的一件事是,如果我使 m_tItems 成为一个指针,那么我可以执行“(*m_tItems)[i]->DoStuff()”并且它工作正常。但我不明白为什么它在非指针版本中不起作用。 (此外,我尝试使用简单的 int 而不是 u32,毫不奇怪,它没有用)

有人知道我做错了什么吗?而且,如果不是微不足道的,为什么它是错误的?

(很抱歉,如果这个问题已经得到解答,我尝试搜索类似的问题,但没有找到与此问题相似的内容)

您需要 2 个版本,一个用于 const,一个不用于 const。一种用于不可变 const JFFVector,另一种用于可变 JFFVector.

在这种情况下,DoSomething是一个const函数,它要调用一个const函数。

template<class T>
class JFFVector
{
public:
    //Init and stuff
    T& operator[](u32 iIndex)
    {
        return m_pData[iIndex + miDataOffset];
    }
    const T& operator[](u32 iIndex) const
    {
        return m_pData[iIndex + miDataOffset];
    }

private:
    T* m_pData;
    u32 m_iDataOffset;
}

有两个索引运算符可以重载——一个适用于 const JFFVector 和 returns 和 T const&,另一个适用于 JFFVector 和 returns一个T&。您只实现了第二个。

您可以像这样类似于非常量版本来实现它:

T const& operator[](u32 iIndex) const   // <-- note the two `const`s
{
    return m_pData[iIndex + miDataOffset];
}

请注意,此重载并非特定于 operator[],而是所有方法(可以由 const 或非 const 重载)。

您在代码中需要 const 版本的原因是 DoSomething() 被声明为 const,因此 this 在该方法中是 const TOtherClass*,并且通过扩展所有它的成员,特别是这里的 m_tItems,在方法中是 const,因此只能对它们调用 const 方法。由于没有为 m_tItems 定义 operator[]const 版本,编译器会给出该错误。

const时,必须留下const。编译器没有简单的方法知道 m_tItems[i] 中发生的事情不会改变 m_tItems,因此违反了 void DoSomething() const 不会改变 TOtherClass 状态的承诺。

解决方案:实现一个constoperator[]

const T& operator[](u32 iIndex) const 
{
    return m_pData[iIndex + miDataOffset];
}