类中调用的重写[]运算符的版本错误
Wrong version of overridden [] operator called in class
我有一个简单的二维线类,它包含两个双向量。我添加了getValue和setValue函数,但更希望公共接口在这些函数的旁边有方括号运算符。以下代码显示了实现和使用:
#include <vector>
#include <algorithm>
#include <cassert>
class Simple2DLine
{
public:
Simple2DLine();
// Simple read method with linear interpolation
double getValue(double x) const;
// Simple write method, adds a curve point, keeping the arrays sorted
void setValue(double x, double y);
double& operator [](double x);
const double operator [](double x) const;
private:
std::vector<double> m_X;
std::vector<double> m_Y;
int getNearestIndex(double x) const;
};
Simple2DLine::Simple2DLine()
{
}
void Simple2DLine::setValue(double x, double y)
{
// Get the index of the point at or just before 'x'
int idx = getNearestIndex(x);
// Check if the exact point already exists.
if (idx >= 0)
{
if (m_X[idx] == x)
{
m_Y[idx] = y;
return;
}
else
{
// Insert adds the value just BEFORE idx, so increment it before inserting.
++idx;
m_X.insert(m_X.begin() + idx,x);
m_Y.insert(m_Y.begin() + idx,y);
return;
}
}
// Otherwise, just insert at the front.
m_X.insert(m_X.begin(),x);
m_Y.insert(m_Y.begin(),y);
}
double Simple2DLine::getValue(double x) const
{
// Make sure there are points - if not, return 0.
if (m_X.size() == 0)
{
return 0;
}
// Make sure it's not out of bounds.
if (x < m_X.front() || x > m_X.back())
{
return 0;
}
// Check if it's at or after the last point
if (x == m_X.back())
{
return m_X.back();
}
// Find the point just before the given point.
int idx = getNearestIndex(x);
// Check if we're on the exact point
if (m_X[idx] == x)
{
return m_X[idx];
}
else
{
// Find the distance from the nearest point and linearly interpolate.
double dist = x - m_X[idx];
return m_Y[idx] + dist * (m_Y[idx + 1] - m_Y[idx]) / (m_X[idx + 1] - m_X[idx]);
}
}
double& Simple2DLine::operator [](double x)
{
// Create a space for the new value
setValue(x,0.0);
int idx = getNearestIndex(x);
return m_Y[idx];
}
const double Simple2DLine::operator [](double x) const
{
return getValue(x);
}
// Returns the index of the point at or just before 'x'. Invalid values return -1.
int Simple2DLine::getNearestIndex(double x) const
{
if (m_X.empty())
{
return -1;
}
std::vector<double>::const_iterator xBegin(m_X.begin());
std::vector<double>::const_iterator xEnd(m_X.end());
// Get an iterator to the first value GREATER than our search value
std::vector<double>::const_iterator it = upper_bound(xBegin,xEnd,x);
// If the iterator is at the beginning, all values are greater
if (it == xBegin)
{
return -1;
}
// Otherwise, decrement the iterator by 1, and return its' distance from the start.
return (it - 1) - xBegin;
}
int main(int argc, char** argv)
{
Simple2DLine tda;
tda.setValue(0.0,10.0);
tda.setValue(1.0,15.0);
tda.setValue(2.0,20.0);
tda.setValue(3.0,25.0);
double tmp = tda.getValue(0.5);
assert(abs(tmp - 12.5) < 0.000001);
tmp = tda.getValue(1.5);
assert(abs(tmp - 17.5) < 0.000001);
tmp = tda.getValue(2.5);
assert(abs(tmp - 22.5) < 0.000001);
// Here, the wrong version of the overridden operator is being called.
tmp = tda[1.5];
tda[2.5] = 22.5;
}
当我以以下方式访问行对象时,运算符的正确版本被称为(非常数)
tda[2.5] = 22.5;
然而,当我尝试使用const版本时,如下所示:
tmp = tda[1.5];
调用非常量版本。我的实现中有错误吗?或者不可能以这种方式访问类?
const版本是在const对象上调用的。所以,如果您有一个像const Simple2DLine tda
一样声明的对象,就会调用operator[]
的const重载版本。
实际上,您将看到const
对象作为函数参数,如:
void foo(const Simple2DLine& tda)
{
std::cout<< tda[0];
}
在那里,您会注意到正在调用const重载函数。
此外,您的const
过载的operator[]
仍然可以返回引用。
您是否认为,仅仅因为包含常量运算符的表达式出现在等式的右侧,就必须自动调用常量运算符?这不是它的工作方式。如果您有一个const对象,则会调用const版本。
例如,您可以尝试将对象分配给常量引用。
Simple2DLine const & tdaconst = tda;
tmp = tdaconst[1.5];
在上面的代码中,将调用const版本。
相关文章:
- 为什么比较运算符如此快速
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 增量运算符与后缀混淆
- 导入库可以跨dll版本工作吗
- 一个关于在C++中重载布尔运算符的问题
- 运算符C++ "delete []"仅删除 2 个前值
- 模板类无法识别友元运算符
- 重载模板化类的[]运算符的常量版本
- 如何为句柄类提供运算符 -> 的常量版本
- 三元运算符 '?:' 在 4.9.0 之前的 GCC 版本中推断出不正确的类型?
- 有两个不同版本的箭头运算符
- R 中 %in% 运算符的C++版本
- 类中调用的重写[]运算符的版本错误
- 为什么我不能在 C++ 中使用模板版本覆盖默认的复制构造函数和赋值运算符
- 运算符重载C++:只读版本
- 为什么逻辑运算符的书面版本没有得到更广泛的应用?
- 为什么cout<< "hello"选择非成员版本的运算符<<?