简体   繁体   English

错误的operator()重载被调用

[英]Wrong operator() overload called

I am writing a matrix class and have overloaded the function call operator twice. 我正在编写一个矩阵类,并且两次重载了函数调用运算符。 The core of the matrix is a 2D double array. 矩阵的核心是2D双数组。 I am using the MinGW GCC compiler called from a windows console. 我正在使用从Windows控制台调用的MinGW GCC编译器。

The first overload is meant to return a double from the array (for viewing an element). 第一个重载旨在从数组中返回一个double(用于查看元素)。 the second overload is meant to return a reference to a location in the array (for changing the data in that location. 第二次重载旨在返回对数组中某个位置的引用(用于更改该位置中的数据。

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

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

I am writing a testing routine and have discovered that the "viewing" overload never gets called. 我正在编写一个测试例程,并且发现从来没有调用过“查看”重载。 for some reason the compiler "defaults" to calling the overload that returns a reference when the following printf() statement is used. 由于某些原因,编译器“默认”为调用使用以下printf()语句时返回引用的重载。

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

I understand that I'm insulting the gods by writing my own matrix class without using vectors and testing with CI/O functions. 我知道我通过编写自己的矩阵类而不使用向量和使用CI / O函数进行测试来侮辱上帝。 I will be punished thoroughly in the afterlife, no need to do it here. 我将在来世受到彻底的惩罚,无需在这里做。

Ultimately I'd like to know what is going on here and how to fix it. 最终,我想知道这里发生了什么以及如何解决。 I'd prefer to use the cleaner looking operator overloads rather than member functions. 我宁愿使用看起来更干净的运算符重载,而不是成员函数。

Any ideas? 有任何想法吗?

The matrix class: irrelevant code omitted. 矩阵类:不相关的代码被省略。


    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];
    }

The testing program: irrelevant code omitted. 测试程序:无关代码被省略。

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
}

The const member function (the "viewing" function) will only be called if the object is const: 仅当对象为const时,才会调用const成员函数(“查看”函数):

const Matrix testMatD(5,7);

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

The overload which is called is determined solely by the parameters (including the this parameter) and not on the return type, or what you do with the return type. 调用的重载仅由参数(包括this参数)确定,而不取决于返回类型或您对返回类型的处理方式。

This means that if you have a non- const method which has a signature that is otherwise identical to a const method (apart from possibly the return type) then the const method will only be used when called on a const object or through a const reference or pointer. 这意味着,如果您有一个非const方法,该方法的签名与const方法相同(除了可能的返回类型),那么只有在const对象或通过const引用调用const方法时,才会使用const方法。或指针。 When you have a non- const object, then non- const method will always be a better match. 当你有一个非const对象,则非const方法将永远是一个更好的匹配。

Typically, the only way to make the distinction on whether you actually write to the returned object is to return some sort of proxy object which has an appropriate implicit conversion for reading and an overloaded assignment operator for writing. 通常,唯一区分您是否实际写入返回对象的方法是返回某种代理对象,该代理对象具有用于读取的适当隐式转换和用于写入的重载赋值运算符。 Needless to say, this usually adds considerable complexity. 不用说,这通常会增加相当大的复杂性。

Hey thanks everybody for your help, I had read similar responses to similar questions. 嘿,谢谢大家的帮助,我对类似问题也有类似的回答。 I guess i just had to hear it one more time worded slightly differently. 我想我只需要再听一次,措词略有不同。

My original problem was i needed two versions of the operator overload to be implemented differently depending on how that operator was being called. 我最初的问题是,我需要两个版本的运算符重载来实现,具体取决于调用该运算符的方式。

-When the user simply needed to read a value, the overload would treat the matrix as const and do bounds checking to make sure the user was not trying to read data that doesn't exist. -当用户只需要读取一个值时,重载会将矩阵视为const并进行边界检查,以确保用户未尝试读取不存在的数据。 -When the user needed to write data, the overload would resize the matrix accordingly. -当用户需要写入数据时,过载将相应地调整矩阵的大小。

of course this makes no sense as the method being called has no knowledge of what is calling it or what the user is trying to do (unless some data is passed in). 当然,这是没有意义的,因为被调用的方法不知道正在调用什么或用户正在尝试做什么(除非传入了一些数据)。

my solution was to make the operator overload execute the same for both a read and a write. 我的解决方案是使操作员重载对于读取和写入执行相同的操作。 thus, if the user attempts to read a location that doesn't exist, the matrix will re-size itself and return a default value. 因此,如果用户尝试读取不存在的位置,则矩阵将自行调整大小并返回默认值。 Ultimately this may sacrifice some speed if the user makes a mistake and reads data that doesn't exist, but if the user is doing that, the speed of the program is the least of his worries. 最终,如果用户犯了一个错误并读取了不存在的数据,这可能会牺牲一些速度,但是如果用户这样做了,那么程序的速度便是他所担心的最少的了。 so this requires that the user be a bit more careful, and i might add a data member that is a flag that indicates whether the matrix has been resized to easily allow the user to check if things went as expected. 因此,这需要用户多加注意,并且我可能会添加一个数据成员,该成员是一个标志,用于指示矩阵是否已调整大小以轻松地允许用户检查事情是否按预期进行。

I'm not going to post the code (unless requested) because this was more a high-level/functional problem, and the code contains so many specifics that it might cloud the discussion. 我将不发布代码(除非要求),因为这是一个高级/功能性问题,并且代码包含太多细节,可能会使讨论蒙上阴影。

As others have mentioned, you need a const object to get a call of a const overload. 正如其他人提到的那样,您需要一个const对象才能调用const重载。

What you are trying to do here is ensure that the reference is transformed into an rvalue for ... . 您要在此处执行的操作是确保将引用转换为...的右值。

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

However, that conversion is performed automatically (§5.2.2/7) so special consideration is unnecessary. 但是,该转换是自动执行的(第5.2.2 / 7节),因此无需特别考虑。

Also, you might as well declare the two overloads to match. 另外,您最好声明两个重载以匹配。 Make the "viewer" return a reference too. 使“查看器”也返回引用。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM