在 C++ 中使用运算符 [] 重载区分读取和写入
distinguish between read and write using operator [] overloading in c++
我得到了一个安全类,它有一个预测数组 - 预测是一个类,它只包含一个双精度。我想允许更改双精度值,但只允许正值,当尝试读取双精度时,如果值未初始化(在我的代码中等于 -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;
我在哪里定义阅读和写作,因为我在阅读和写作时做不同的事情。
谢谢
你不能在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;
}
使用转换运算符和转换构造函数的组合,可以获得此行为。 此示例代码应让您了解需要如何实现类:
class Foo
{
int value;
public:
Foo() { value = -1; }
Foo(int value) {
if (value < 0) cout << "errorn"; else { cout << "okn"; this->value = value; }
}
operator int() { if (value < 0) cout << "errorn"; else return value; }
};
class Bar
{
Foo * fooArray;
public:
Bar() { fooArray = new Foo[4]; }
Foo & operator [](int i) { return fooArray[i]; }
};
int main()
{
Bar test;
int foobar = test[0];
test[1] = 4;
test[2] = -4;
cin.get();
return 0;
}
输出:
error
ok
error
中心思想如下:与其返回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;
}
演示。
请注意,此方案也可用于更复杂的操作。例如:通知观察者模式中的依赖类。
几点
-
predArray 数组应该是 Security 的成员(未在示例代码中显示)
-
通过 [] 运算符进行的索引访问应该在 Security 实例上,而不是 predArray 上。变量 predArray 是对象的原始数组,而不是保存数组的对象。
例如:
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;
- 在 Prediction::operator double()
- 和 Prediction::operator=(const double 值) 上添加正值检查,在 return 语句之前;
相关文章:
- 0xC0000005:访问冲突读取位置 0x00000000. 重载 == 运算符的问题
- 从文件重载运算符>>读取单词
- 重载>>运算符和读取字符
- 重载时读取并插入到向量中 []
- 重载>>运算符以读取文本文件
- 重载>>以分数读取
- 如何使用ATA命令读取磁盘的特定扇区
- 如何在重载提取运算符中读取行(忽略空格字符)
- 重载 C++ 运算符>>,以便我可以读取向量(向量<int>向量;
- 堆重载的2-D矩阵和c++中的读取文件
- 有关重载用于读取文本文件的输入运算符>>的问题
- 运算符 [] 重载写入/读取之间的区别
- iStream 重载 - 从文件中读取字符串
- 重载运算符 =,读取字符串时出错
- GMtime 不适用于使用重载运算符读取的对象
- 原始读取带有 fstream 的引导扇区
- C++提取器 (>>) 重载不读取和分配矩阵类
- 运算符重载实现:0xC0000005:读取位置存在访问冲突
- 函数重载和读取fdump-tree-all输出
- 在 C++ 中使用运算符 [] 重载区分读取和写入