Конструктор копирования шаблона C ++, компилятор говорит, «передавая const, поскольку этот аргумент отбрасывает квалификаторы» quot;

Я пытаюсь создать шаблон класса динамических матриц. Благодаря моим текущим знаниям C ++ мне удалось решить некоторые проблемы, но я застрял в конструкторе копирования и перегрузке operator =; другими словами, я не могу создавать копии своих объектов.
По моему мнению, это должно сработать, но мой друг, компилятор, говорит мне, что у меня есть 1 ошибка:
ошибка: передача const Matrix в качестве аргумента this для int Matrix :: getElement (int, int) [with T = int] ’отбрасывает квалификаторы [-fpermissive] в этой строке:

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

когда я хочу создать объект:

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

Мой шаблонный класс находится здесь:

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

Как я могу понять из этой ошибки, я создаю 2 объекта, которые ссылаются на один и тот же блок памяти, но я хочу создать 2 объекта, которые ссылаются на 2 разных блока памяти с одинаковым содержимым.

4

Решение

В вашем экземпляре конструктор

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

original объявляется как постоянная ссылка, и это очень хорошо. Однако это означает, что вы не должны вызывать какие-либо методы Matrix<T> на нем, которые не объявлены как const функции.

getElement функция не объявлена ​​как const так что вы не можете использовать его внутри конструктора копирования. Решите это, объявив это как const-функцию:

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

Что это значит:

  1. Эта функция может быть вызвана на Matrix объекты, которые являются постоянными (такими как original в вашем экземпляре конструктора)

  2. Вы не можете выполнять какие-либо действия внутри getElement который изменяет текущий экземпляр Matrix (то есть, который изменяет *this).

Первое — это то, что мы хотим, а второе — не проблема, потому что getElement это просто метод получения, поэтому он не должен ничего менять.

Обратите внимание, что из-за этого, это хорошая идея всегда помечать функции-члены как const когда они не должны ничего менять. Это означает, что вы можете применить их к константным объектам, и это означает, что компилятор скажет вам, если вы по ошибке поместите код в функцию, которая действительно что-то изменяет.

Последнее замечание: Как указал Торе Олсен, getElement функция, вероятно, должна возвращать объект или ссылку типа T скорее, чем int,

8

Другие решения

Как я уже говорил, когда вы начинаете писать constВы не можете остановиться до конца. Потому что const объект может использовать метод const и только метод const. Однако, правильность const важна для программиста C ++. Однажды я прочитал статью об этом, к сожалению, она была на французском, но я думаю, что ее легко найти на английском. Это объясняет, что правильность const обеспечивает безопасность в вашей программе. И это помогает для некоторых оптимизаций, но здесь я не могу точно вспомнить точку зрения автора.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector