确定operator []用途的目的

时间:2011-01-20 13:31:19

标签: c++ class methods operators operator-overloading

假设我的容器类中有以下方法:

Datatype& operator[](const unsigned int Index) // I know this should use size_t instead.
{
    return *(BasePointer + Index); // Where BasePointer is the start of the array.
}

我想对MyInstance[Index] = Value用法实施某种边界检查,以便当用户尝试更改其范围之外的值时,容器会自动调整大小。但是,如果用户试图访问超出容器范围的值,我希望发生其他事情,例如MyVariable = MyInstance[Index]。如何检测operator[]的使用方式?

3 个答案:

答案 0 :(得分:5)

草图:

返回代理对象而不是实际的数据条目。然后,代理对象定义operator =来处理赋值情况,并定义隐式转换运算符以用于读出案例。

template <typename T>
class AccessorProxy {
  friend class Container<T>;
public:
    AccessorProxy(Container<T>& data, unsigned index)
        : data(data), index(index) { }
    void operator =(T const& new_value) {
        // Expand array.
    }
    operator const T&() const {
        // Do bounds check.
        return *(data.inner_array + index);
    }
private:
    AccessorProxy(const AccessorProxy& rhs)
     : data(rhs.data), index(rhs.index) {}
    AccessorProxy& operator=(const AccessorProxy&);
    Container<T>& data;
    unsigned index;
};

template <typename T>
class ConstAccessorProxy {
  friend class Container<T>;
public:
    ConstAccessorProxy(const Container<T>& data, unsigned index)
        : data(data), index(index) { }
    operator const T&() const {
        // Do bounds check.
        return *(data.inner_array + index);
    }
private:
    ConstAccessorProxy(const ConstAccessorProxy& rhs)
     : data(rhs.data), index(rhs.index) {}
    ConstAccessorProxy& operator=(const ConstAccessorProxy&);
    const Container<T>& data;
    unsigned index;
};

AccessorProxy<Datatype> operator[](const unsigned int Index)
{
    return AccessorProxy<Datatype>(*this, Index);
}
ConstAccessorProxy<Datatype> operator[] const (const unsigned int Index)
{
    return ConstAccessorProxy<Datatype>(*this, Index);
}

访问者类可能需要成为容器类的朋友。

找到避免代码重复的方法留给读者练习。 :)

答案 1 :(得分:2)

使用虚拟类类型来表示MyInstance[Index]之类的表达式,并延迟确定在使用该表达式之前要执行的操作。

class MyContainer {
private:
    class IndexExpr {
    public:
        // Get data from container:
        operator const Datatype&() const;
        // Expand container if necessary, then store data:
        Datatype& operator=(const Datatype& value);

        // Treat MyInstance[i] = MyInstance[j]; as expected:
        Datatype& operator=(const IndexExpr& rhs)
        { return *this = static_cast<const Datatype&>(rhs); }
    private:
        IndexExpr(MyContainer& cont, unsigned int ind);
        MyContainer& container_;
        unsigned int index_;
        friend class MyContainer;
    };

public:
    IndexExpr operator[](unsigned int Index)
    { return IndexExpr(*this, Index); }

    // No IndexExpr needed when container is const:
    const Datatype& operator[](unsigned int Index) const;

    // ...
};

答案 2 :(得分:1)

这不是“如何检测”的完美答案,但是,如果用户通过const实例访问operator[],则在索引超出范围时抛出异常。 即。

Datatype const& operator[]() const { .. // don't modify here, throw exception

但是,如果用户通过非const实例访问实例,那么如果索引超出范围(并且在可接受的范围内),则无论如何都要扩展

Datatype& operator[]() { .. // modify here

基本上,您正在使用实例的const属性来确定您的语义是什么(如std::map中所做的那样 - 即尝试在地图的const实例上调用operator[]会导致编译器错误 - 即map没有const限定operator[],因为如果密钥不存在,则保证函数创建映射。)

相关问题