No matching constructor for initialization, c ++ Error

3

I have a Matrix class that has a copy constructor and an add method that adds the matrix to another and returns a new matrix, but I can not use the copy constructor with this method.

#include <iostream>
#include "matrix.h"
#include "methods.h"

using namespace std;
int main()
{
    unsigned int n;
    cin >> n;
    Matrix a(n,n);
    cin >> a;
    Matrix b(a);
    Matrix c(a.add(b));
    c.print();
}

The Matrix line b (a) works without errors and the add method works correctly but the Matrix line c (a.add (b)) gives me the error: no matching constructor for initialization of 'Matrix'. If I use a.add (b) .print () everything works correctly. because I can not pass the result of the method to the constructor ??

This is the Matrix class:

Matrix::Matrix() : Matrix(3, 3){}

Matrix::Matrix(unsigned int rows, unsigned int cols){
    this->rows = rows;
    this->cols = cols;
    this->array = std::vector<std::vector<double>>(rows, std::vector<double>(cols));
    fill(0);
}

Matrix::Matrix(Matrix& m) : Matrix(m.getRows(), m.getCols()){
    array = m.array;
}

void Matrix::map(std::function<double(unsigned int i, unsigned int j)> f){
    for(unsigned int i = 0; i < rows; i++){
        for(unsigned int j = 0; j < cols; j++){
            array[i][j] = f(i, j);
        }
    }
}

void Matrix::fill(double d){
    map([&](int, int)->double{ return d;});
}

void Matrix::print(){
    for (unsigned int i = 0; i < rows; ++i) {
        std::cout << array[i][0];
        for (unsigned int j = 1; j < cols; ++j) {
            std::cout << " " << array[i][j];
        }
        std::cout << std::endl;
    }
}

unsigned int Matrix::getRows(){
    return rows;
}

unsigned int Matrix::getCols(){
    return cols;
}

Matrix Matrix::add(Matrix m){
    assert(rows == m.rows && cols == m.cols);
    Matrix res(rows, cols);
    res.map([&](unsigned int i, unsigned int j)->double{ return array[i][j]+m.array[i][j];});
    return res;
}
...
    
asked by Joaquin 30.09.2018 в 19:49
source

1 answer

3

The functions involved are these:

Matrix::Matrix(Matrix& m)
Matrix Matrix::add(Matrix m);

That is, the constructor expects to receive a L-value (I recommend reading this other question ) and, however, the add function returns an R-value and the requested conversion is not valid.

In other words, the conversion is not valid because add returns a value . And the only receiver of that object is the copy constructor, that is, after the call the object will cease to exist. This short life cycle prevents you from passing it as a reference without more ... the reference should be, in this case, constant :

Matrix::Matrix(Matrix const& m);
//                    ~~~~~ Importante!!!

Now, if you make this change the code will still not compile because this constructor tries to call getRows() and getCols() and these methods are not labeled as const , then can not be called if the object it is constant . The solution to this problem is as simple as labeling these methods as const (something that makes sense since these methods should not modify the state of the current object):

unsigned int getRows() const;
unsigned int getCols() const;
    
answered by 30.09.2018 / 22:30
source