4

動的マトリックスのテンプレート クラスを作成しようとしています。私の現在の C++ の知識で、いくつかの問題を解決することができましたが、コピー コンストラクターとオーバーロード operator=; で行き詰まっています。つまり、オブジェクトのコピーを作成できません。私の意見では、これはうまくいくはずですが、私の友人であるコンパイラは、エラーが 1 つあると教えてくれました。 ]' は、次の行で修飾子 [-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

2 に答える 2

10

コピー コンストラクターで

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

originalは const 参照として宣言されており、これは非常に優れています。Matrix<T>ただし、関数として宣言されていないメソッドを呼び出してはならないことを意味しますconst

getElement関数は as として宣言されてconstいないため、コピー コンストラクター内では使用できません。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型のオブジェクトまたは参照を返す必要があります。Tint

于 2012-10-17T07:16:54.243 に答える
1

私がよく言うように、書き始めるとconst最後まで止まらない。const オブジェクトは const メソッドと const メソッドのみを使用できるためです。ただし、C++ プログラマーにとって const の正確性は重要です。それについての記事を一度読んだことがありますが、残念ながらフランス語でしたが、英語では見つけやすいと思います。const-correctness がプログラムに安全性とセキュリティをもたらすことを説明しました。また、いくつかの最適化に役立ちますが、ここでは著者のポイントを正確に思い出せません。

于 2012-10-17T07:24:53.953 に答える