调用错误的operator()重载

时间:2010-04-09 23:57:42

标签: c++ debugging gcc matrix operator-overloading

我正在编写一个矩阵类,并且已经重载了函数调用操作符两次。矩阵的核心是2D双阵列。我正在使用从Windows控制台调用的MinGW GCC编译器。

第一个重载是从数组中返回一个double(用于查看元素)。 第二个重载是为了返回对数组中某个位置的引用(用于更改该位置的数据。

double operator()(int row, int col) const ; //allows view of element

double &operator()(int row, int col); //allows assignment of element

我正在编写测试例程,并发现“查看”超载永远不会被调用。由于某种原因,当使用以下printf()语句时,编译器“默认”调用返回引用的重载。

fprintf(outp, "%6.2f\t", testMatD(i,j));

据我所知,我通过编写自己的矩阵类而不使用向量和使用C I / O函数进行测试来侮辱众神。我将在来世彻底受到惩罚,不需要在这里做。

最终,我想知道这里发生了什么,以及如何解决它。我更喜欢使用更清晰的运算符重载而不是成员函数。

有什么想法吗?

矩阵类:省略不相关的代码。


    class Matrix

    {
    public:
 double  getElement(int row, int col)const; //returns the element at row,col

 //operator overloads
 double operator()(int row, int col) const ; //allows view of element
 double &operator()(int row, int col); //allows assignment of element

    private:
 //data members
 double  **array;   //pointer to data array

    };

    double Matrix::getElement(int row, int col)const{
  //transform indices into true coordinates (from sorted coordinates
  //only row needs to be transformed (user can only sort by row)
  row = sortedArray[row];

  result = array[usrZeroRow+row][usrZeroCol+col];
  return result;
    }

    //operator overloads
    double Matrix::operator()(int row, int col) const {
     //this overload is used when viewing an element
     return getElement(row,col);
    }

    double &Matrix::operator()(int row, int col){
     //this overload is used when placing an element
  return array[row+usrZeroRow][col+usrZeroCol];
    }

测试程序:省略了无关代码。

int main(void){

 FILE *outp;

 outp = fopen("test_output.txt", "w+");

    Matrix testMatD(5,7); //construct 5x7 matrix

    //some initializations omitted
    fprintf(outp, "%6.2f\t", testMatD(i,j));   //calls the wrong overload
}

4 个答案:

答案 0 :(得分:5)

只有当对象为const时才会调用const成员函数(“查看”函数):

const Matrix testMatD(5,7);

testMatD(1, 2); // will call the const member function

答案 1 :(得分:3)

调用的重载仅由参数(包括this参数)决定,而不是返回类型,或者您对返回类型执行的操作。

这意味着,如果您的非const方法具有与const方法相同的签名(除了可能的返回类型),那么const方法仅在const对象或const引用或指针上调用时使用。当您拥有非const对象时,非const方法将始终是更好的匹配。

通常,区分是否实际写入返回对象的唯一方法是返回某种代理对象,该代理对象具有适当的隐式转换以及用于写入的重载赋值运算符。不用说,这通常会增加相当大的复杂性。

答案 2 :(得分:1)

嘿,谢谢大家的帮助,我已经阅读了类似问题的类似回答。我想我只能再听一次措辞略有不同。

我最初的问题是我需要两个版本的运算符重载,这取决于调用该运算符的方式。

- 当用户只需要读取一个值时,重载会将矩阵视为const并进行边界检查以确保用户没有尝试读取不存在的数据。 - 当用户需要写入数据时,重载会相应地调整矩阵的大小。

当然这没有任何意义,因为被调用的方法不知道调用它的内容或用户尝试做什么(除非传入一些数据)。

我的解决方案是让操作符重载对读取和写入执行相同的操作。因此,如果用户试图读取不存在的位置,则矩阵将重新调整其大小并返回默认值。最终,如果用户犯了错误并读取不存在的数据,这可能会牺牲一些速度,但如果用户这样做,程序的速度是他最不担心的。因此,这需要用户更加小心,我可能会添加一个数据成员,该成员是一个标志,指示矩阵是否已调整大小以便用户轻松检查事情是否按预期进行。

我不打算发布代码(除非请求),因为这更像是一个高级/功能问题,而且代码包含很多细节,可能会使讨论变得模糊。

答案 3 :(得分:0)

正如其他人所提到的,您需要一个const对象才能调用const重载。

您在此尝试执行的操作是确保将引用转换为...的右值。

fprintf(outp, "%6.2f\t", double( testMatD(i,j) ) ); // double() for temporary

但是,转换是自动执行的(§5.2.2/ 7),因此不需要特别考虑。

此外,您还可以声明要匹配的两个重载。让“查看者”也返回参考。

double const &operator()(int row, int col) const ; //allows view of element