运算符重载:C++

Operator Overloading: C++

本文关键字:C++ 重载 运算符      更新时间:2023-10-16

我有一个关于C++中运算符重载的问题。

对于一个赋值,我必须编写一个包含数组的类,有点像Java中的ArrayList。

我要做的一件事就是跟踪数组的大小。Size是包含的元素数量,而capacity是在类必须扩展数组之前可以包含的最大数量。

客户端代码在调用构造函数时指定大小。然而,当添加新元素时,我必须想办法更改大小。

我的老师说了一些关于能够为平等的不同方面重载运算符的内容。这是真的吗,还是我误解了她?如果这有效的话,这将是我的问题的最佳解决方案。

我目前对[]操作员的过载是:

int & ArrayWrapper::operator [] (int position){
if(position == _size){
    if(_size == _capacity){
        changeCapacity(_capacity+10);
    }
}
return _array[position];
}

这对于检索来说很好,但我希望有它,这样如果有人从'='的左手边调用它,它就会检查是否需要扩展大小。

编辑:如果这不是真的,有人能想出不同的解决方案吗?我想到的一个解决方案是每次调用getSize()方法时都只遍历整个数组,但我真的不想使用这个解决方案,因为它看起来很俗气。

编辑:为了澄清,我不是在问我对数组的扩展是否有效。每次添加新元素时,我都需要在大小上加1。例如,如果客户端创建了一个大小为15、容量为25的数组,然后尝试向array[15]添加一些内容,则应该将大小增加到16。我想知道是否有办法在超载的情况下做到这一点。

一个简单的方法是重载数组是const还是可变的,这并不能完全满足您的需要。

这并不能区分数组是在赋值的左侧使用(作为左值)还是在右侧使用(作为右值

// Mutable overload (returns a mutable reference)
int & operator[](size_t position) {
    if (position >= _size) {
        if (position >= _capatity) {
           // increase capacity
        }
        // increase size
    }
    return _array[position];
}
// Const overload (returns a value or const reference)
int operator[](size_t position) const {
    if (position >= _size) {
        throw std::out_of_range("Array position out of range");
    }
    return _array[position];
}

如果你真的想知道你是否被分配到,那么你必须返回一个代理作为引用。这重载了向数组写入的赋值,并提供了一个转换运算符来获取元素的值:

class proxy {
public:
    proxy(ArrayWrapper & array, size_t position) :
        _array(array), _position(position) {}
    operator int() const {
        if (_position >= _array._array._size) {            
            throw std::out_of_range("Array position out of range");
        }
        return _array._array[_position];
    }
    proxy & operator=(int value) {
        if (_position >= _size) {
            if (_position >= _capatity) {
                // increase capacity
            }
            // increase size
        }
        _array._array[_position] = value;
        return *this;
    }
private:
    ArrayWrapper & _array;
    size_t _position;
};

您可能需要将其声明为ArrayWrapperfriend;然后从operator[]:返回

proxy ArrayWrapper::operator[](size_t position) {
    return proxy(*this, position);
}

这种方法很好。不过,代码中有一个错误:如果有人调用的运算符的位置等于数组的当前大小加100,会发生什么?

问题是您是否真的想要根据你在=的哪一边。你的基本想法会很好,但会无论你在哪一边,都要扩展阵列,例如:

ArrayWrapper a(10);
std::cout << a[20] << std::end;

将导致扩展阵列。在这种情况下,优选的行为是上面的代码引发异常,但对于

ArrayWrapper a(10);
a[20] = 3.14159;

工作。使用代理可以做到这一点:首先,定义double ArrayWrapper::get( int index ) constvoid ArrayWrapper::set( int index, double newValue );如果索引超出了界限,但是setter将扩展数组。然后operator[]返回一个代理,行为:

class ArrayWrapper::Proxy
{
    ArrayWrapper* myOwner;
    int           myIndex;
public:
    Proxy( ArrayWrapper& owner, int index )
        : myOwner( &owner )
        , myIndex( index )
    {
    }
    Proxy const& operator=( double newValue ) const
    {
        myOwner->set( myIndex, newValue );
    }
    operator double() const
    {
        return myOwner->get( myIndex );
    }
};

如果您不熟悉operator double(),它是重载转换运算符。其工作方式是,如果operator[]在分配的左侧,它实际上是被分配到的代理,以及proxy转发到CCD_ 11函数。否则,代理将隐式转换为double,并且此转换转发到CCD_ 13功能。