C ++ template instance constructor, the compiler says: "Skip const because this argument discards qualifiers"

I am trying to create a dynamic matrix template class. With my current knowledge of C ++, I managed to solve some problems, but I was stuck in the copy constructor and overloaded operator =; in other words, I cannot create copies of my objects. In my oppinion, this should work, but my friend, the compiler, tells me that I have 1 error: error: pass' const Matrix as' this argument 'int Matrix :: getElement (int, int) [with T = int] discards qualifiers [-fpermissive] on this line:

m[i][j] = original.getElement(i, j); 

when i want to create an object:

 Matrix<int> m = Matrix<int>(3, 3); 

My template class is here:

 template<class T>class Matrix { public: Matrix<T>(int lines, int columns) { this->lines = lines; this->columns = columns; T* aux = new T[this->lines * this->columns]; m = new T*[lines]; for (int i = 0; i < this->lines; i++) { m[i] = aux + (i * this->columns); } for (int i = 0; i < this->lines; i++) { for (int j = 0; j < this->columns; j++) { m[i][j] = 0; } } } Matrix<T>(const Matrix<T>& original) { columns = original.getColumns(); lines = original.getLines(); T* aux = new T[this->lines * this->columns]; m = new T*[lines]; for (int i = 0; i < lines; i++) { m[i] = aux + (i * this->columns); } for (int i = 0; i < lines; i++) { for (int j = 0; j < columns; j++) { m[i][j] = original.getElement(i, j); } } } virtual ~Matrix<T>() { /*for (int i = lines - 1; i > 0; i--) { delete m[i]; }*/ delete [] m; } T** getPointer() { return m; } int getLines () const { return lines; } int getColumns () const { return columns; } int getElement(int line, int column) { return m[line][column]; } int setElement(int line, int column, T value) { m[line][column] = value; } Matrix<T>* getTranspose() { Matrix<T>* aux = new Matrix<T>(lines, columns); for (int i = 0; i < lines; i++) { for (int j = 0; j < columns; j++) { aux->setElement(i,j, m[j][i]); } } return aux; } Matrix<T> operator=(const Matrix<T> original) { columns = original.getColumns(); lines = original.getLines(); T* aux = new T[this->lines * this->columns]; m = new T*[lines]; for (int i = 0; i < lines; i++) { m[i] = aux + (i * this->columns); } for (int i = 0; i < lines; i++) { for (int j = 0; j < columns; j++) { m[i][j] = original.getElement(i, j); } } } friend std::ostream& operator<<(std::ostream& out, Matrix<T>& matrix) { out<<"Matrix:"<<std::endl; for (int i = 0; i < matrix.getLines(); i++) { for (int j = 0; j < matrix.getColumns(); j++) { out<<matrix.getElement(i, j)<<" "; } out<<std::endl; } return out; } friend std::istream& operator>>(std::istream& in, Matrix<T>& matrix) { std::cout << "Reading Matrix:\n"; for (int i = 0; i < matrix.getLines(); i++) { for (int j = 0; j < matrix.getColumns(); j++) { std::cout << "Matrix[" << i << "][" << j << "]:"; in >> matrix.m[i][j]; } std::cout << std::endl; } return in; } private: T** m; int lines; int columns; }; 

As I can understand from this error, I create 2 objects that refer to the same memory block, but I want to create 2 objects that refer to 2 different memory blocks with the same contents.

+4
source share
2 answers

In your copy constructor

 Matrix<T>(const Matrix<T>& original) 

original declared as a reference to a constant, and this is very good. However, this means that you should not call on it any Matrix<T> methods that are not declared as const functions.

The getElement function is not declared as const , so you cannot use it inside the copy constructor. Solve this by declaring it as a const function:

 int getElement(int line, int column) const // <--- Note the 'const' { return m[line][column]; } 

What does it mean:

  • This function can be called on Matrix objects that are const (for example, original in your copy constructor)

  • You cannot perform any action inside getElement that modifies the current Matrix instance (i.e. modifies *this ).

The former is what we want, and the latter is not a problem, because getElement is just a getter method, so it does not need to change anything.

Note that because of this, it is recommended that you always mark member functions as const when they should not change anything. This means that you can apply them to persistent objects, and that means that the compiler will tell you if you mistakenly insert code into a function that actually modifies something.

Final note: As Tore Olsen noted, the getElement function should probably return an object or reference of type T , not int .

+8
source

As I usually say, when you start writing const , you cannot stop to the end. Because the const object can use the const method and only the const method. However, const-correctness is important for a C ++ programmer. I read an article about this once, unfortunately, it was in French, but I think it is easy to find in English. It explains that const-correctness provides security and safety in your program. And this helps for some optimizations, but here I can’t remember the exact point of the author.

+1
source

Source: https://habr.com/ru/post/1440226/


All Articles