使用c ++中的operator []重载来区分读和写

时间:2015-06-12 15:26:29

标签: c++ overloading operator-keyword

我有一个具有预测数组的安全类 - 预测是一个Class,只保留一个double。 我想允许更改double的值,但只允许正值, 当尝试读取double时,如果值未初始化(在我的代码中等于-1)则抛出异常。 我也有双操作员 这样的事情:

class Prediction{
    double value;
public:
    .....
    Prediction::operator double() const {
        return this->prediction;
    }
    Prediction::operator=(const double value){
       ...
        //check value
    }

}

class Security{
   ...
    Prediction& Security::operator[](int index){
        return predArray[index];
    }
}

Prediction *predArray = new Prediction[4];
//default constructor set the value -1;

double a = predArray[0] //should throw an exception, because predArray[0] = -1
predArray[0] = 4; //should be O.K. because I want to change the value
predArray[1] = -4; //should throw exception, because trying to put negative value;

我在哪里定义阅读和写作,因为我在阅读和写作时做了不同的事情。

感谢

4 个答案:

答案 0 :(得分:3)

你不能在operator[]中这样做。操作员无法知道如何使用它返回的值。因此,您必须根据返回的对象执行此操作。通过抛出返回对象的赋值运算符,您可以很容易地处理负值的赋值。

Prediction::operator=(const double value){
    if (value < 0)
        throw something;
    ...
}

如果你想要这句话:

double a = predArray[0];

您必须在转换为双重操作符时执行此操作。

Prediction::operator double() const {
    if (value < 0)
        throw something;
    return value;
}

答案 1 :(得分:1)

使用转换运算符和转换构造函数的组合可以获得此行为。此示例代码应该让您了解如何实现类:

error
ok
error

输出:

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="com.evs.demo.layout.FixedScrollingViewBehavior">
    .....   
</android.support.v4.widget.NestedScrollView>

答案 2 :(得分:1)

主要思想如下:您可以返回一个带有重载double&的代理(以及其他必要的代码),而不是返回operator=。然后,代理执行检查。

struct reference_proxy
{
    reference_proxy(double &_d) : d(_d) {}
    reference_proxy& operator=(double rhs)  //operator= throws when rhs<0
    {
        if(rhs<0.0)
        {
            std::cout<<"throw exception"<<std::endl;
        }
        else
        {
            std::cout<<"ok"<<std::endl;
            d = rhs;
        }
        return *this;
    }

    operator double ()  //cast to double gives an error when uninitialized
    {
        if(d<0.0)
        {
            std::cout<<"throw exception"<<std::endl;
        }
        return d;
    }

    // add further required functions like operator+= etc.
private:
    double& d;
};

然后你可以在其他课程中使用它:

struct Prediction
{
     operator double& () { return d; }
     double d = -1.0;
};

struct Security
{
    template<typename ... Args>
    Security(Args&& ... args) : v(std::forward<Args>(args) ...) {}

     auto operator[](int i)
     {
         return reference_proxy(v[i]);
     }
    std::vector<Prediction> v;
};

应用:

int main()
{
    Security s(10);   

    double a = s[0]; //prints "throw exception"
    s[0] = 4;        //prints "ok"
    s[1] = -4;       //prints "throw exception"

    return 0;
}

DEMO

请注意,此方案也可用于更复杂的操作。例如:以观察者模式通知依赖类。

答案 3 :(得分:0)

几点

  1. predArray 数组应该是Security的成员(未在示例代码中显示)

  2. 通过[]运算符的索引访问应该在Security的实例上,而不是 predArray 。变量 predArray 是一个原始的对象数组,而不是包含数组的对象。

  3. 例如:

    Security o = new Security();
    double a = o[0] //should throw an exception, because predArray[0] = -1
    o[0] = 4; //should be O.K. because I want to change the value
    o[1] = -4; //should throw exception, because trying to put negative value;
    
    1. 在return语句之前添加 Prediction :: operator double() Prediction :: operator =(const double value)的正值检查;