我正在实现一个小的密集矩阵类,而不是计划get / set运算符,我想使用运算符重载来使API更加可用和连贯。
我想要实现的目标非常简单:
template<typename T>
class Matrix
{
public:
/* ... Leaving out CTOR and Memory Management for Simplicity */
T operator() (unsigned x, unsigned y){/* ... */ }
};
Matrix<int> m(10,10);
int value = m(5,3); // get the value at index 5,3
m(5,3) = 99; // set the value at index 5,3
虽然通过重载operator()
来直接获取值,但我无法理解定义setter。根据我的理解,运算符优先级会在赋值之前调用operator()
,但是不可能重载operator()
来返回正确的左值。
解决此问题的最佳方法是什么?
答案 0 :(得分:8)
我认为“做出正确的事情是不可能的”:
struct Matrix
{
int & operator()(size_t i, size_t j) { return data[i * Cols + j]; }
const int & operator()(size_t i, size_t j) const { return data[i * Cols + j]; }
/* ... */
private:
const size_t Rows, Cols;
int data[Rows * Cols]; // not real code!
};
现在你可以说,m(2,3) = m(3,2) = -1;
等。
答案 1 :(得分:0)
您的问题的答案是Kerrek已经说过:您可以通过更改运算符的签名来提供重载,在这种情况下可以通过修改函数的常量来实现。
但我建议您至少考虑为值提供单独的setter。原因是,一旦您返回对内部数据结构的引用,您就无法控制外部代码对数据的作用。在这种情况下可能没问题,但考虑到如果您决定在实现中添加范围验证(即验证矩阵中的值不高于X或低于Y),或者希望优化矩阵上的某些计算(比如说矩阵中所有元素的总和是经常检查的值,并且您希望通过预先缓存值并在每次字段更改时更新它来优化计算)使用接收值的方法更容易控制设置。