C++ 模板复制构造函数,编译器说 "passing const as this argument discards qualifiers"

标签 c++ templates compiler-errors operator-overloading copy-constructor

我正在尝试创建动态矩阵的模板类。凭借我目前对 C++ 的了解,我设法解决了一些问题,但我被复制构造函数和重载 operator=; 困住了。换句话说,我无法创建对象的拷贝。 在我看来这应该可行,但我的编译器 friend 告诉我有 1 个错误: 错误:将“const Matrix”作为“int Matrix::getElement(int, int) [with T = int]”的“this”参数传递会丢弃此行的限定符 [-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 个具有相同内容的不同内存块。

最佳答案

在你的复制构造函数中

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

original被声明为 const 引用,这非常好。但是,这意味着您不能调用 Matrix<T> 的任何方法。在其上未声明为 const功能。

getElement函数未声明为 const所以你不能在复制构造函数中使用它。通过将其声明为常量函数来解决此问题:

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

这意味着:

  1. 这个函数可以在Matrix上调用const 对象(例如复制构造函数中的 original)

  2. 您不能在 getElement 中执行任何操作修改 Matrix 的当前实例(即修改 *this )。

前者是我们想要的,后者不是问题,因为getElement只是一个getter方法,所以它不需要修改任何东西。

请注意,因此,始终 将成员函数标记为 const 是个好主意当他们不应该修改任何东西时。这意味着您可以将它们应用于常量对象,这意味着编译器会告诉您是否错误地将代码放入实际上确实修改了某些内容的函数中。

最后的评论:正如 Tore Olsen 所指出的,getElement函数应该返回类型为 T 的对象或引用而不是 int .

关于C++ 模板复制构造函数,编译器说 "passing const as this argument discards qualifiers",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12929014/

相关文章:

.net - 使用自定义应用程序分发 microsoft.visualstudio.texttemplating.dll

c++ - 是否有一些技巧可以让我将流操纵器传递给可变参数模板函数?

java - ';'表达式错误的预期和非法开始

c++ - 使用Vector函数C++从文件中读取特定数据

c++ - 使用方法和对象创建功能对象

c++ - 如何在C/C++中设置获取互斥量的优先级

c# - 在IQueryProvider的实现中构造Linq.EnumerableQuery时出现编译器错误

c++ - 响应式地检查两个队列而不 Hook CPU

c++ - 从函数参数的返回类型推导出函数返回类型

c# - C#条件对象声明