C ++ оператор + и оператор + = перегрузка - PullRequest
9 голосов
/ 08 декабря 2010

Я реализую свой собственный класс матрицы в C ++, чтобы помочь мне развить мое понимание языка. Я где-то читал, что если у вас есть работающий оператор + =, используйте его в вашем операторе +. Вот что у меня есть:

template <class T>
const Matrix<T>& Matrix<T>::operator+(const Matrix<T> &R){

    Matrix<T> copy(*this);
    return copy += R;
}

А вот перегрузка оператора + =:

template <class T>
const Matrix<T>& Matrix<T>::operator+=(const Matrix<T> & second_matrix){
    //Learn how to throw errors....
    if (rows != second_matrix.getNumRows() || cols != second_matrix.getNumCols()){throw "Dimension mismatch.";}
    int i,j;
    for (i = 0; i < rows; i++){
        for (j = 0; j < cols; j++){
            data[i][j] += second_matrix.get(i,j);
        }
    }
    return *this;
}

Я могу использовать + = просто отлично (например, a + = b; не возвращает ошибок). Но вызов оператора + (например, a = b + c;) возвращает:

test.cpp.out(77055) malloc: *** error for object 0x300000004: pointer being freed was not allocated

Просто для полноты вот мой деструктор:

template <class T>
Matrix<T>::~Matrix(){
    for (int i = 1; i < rows; i++){
        delete[] data[i]; }
    delete[] data;
}

Я использую C ++ в течение нескольких лет, и у меня иногда возникают проблемы с отслеживанием указателей. Надеюсь это нормально ... Любая помощь будет отличной. Спасибо!

РЕДАКТИРОВАТЬ: вот мой конструктор копирования. Это было установлено, чтобы освободить массивы данных, но я удалил это. теперь я получаю ошибки сегментации.

template <class T>
Matrix<T>::Matrix(const Matrix<T>& second_matrix){

    rows = second_matrix.getNumRows();
    cols = second_matrix.getNumCols();
    data = new T*[rows];

    int i,j;
    for (i = 0; i < rows; i++){
        data[i] = new T[cols];
    }
    for (i = 0; i < rows; i++){
        for (j = 0; j < cols; j++){
            data[i][j] = second_matrix.get(i,j);
        }
    }

}

Ответы [ 3 ]

22 голосов
/ 08 декабря 2010

operator+() не должен возвращать ссылочный тип, поскольку это новый (локально объявленный) экземпляр, содержащий результат операции.

2 голосов
/ 08 декабря 2010

Вот как я реализовал такие операторы для класса Matrix , это основано на Vector Class .Как только вы определили некоторые операторы, все остальные должны быть определены в терминах простейших операторов:

Matrix::Matrix(const Matrix& rMatrix) :
    _iRows(rMatrix._iRows), _iColumns(rMatrix._iColumns), _pVector(0)
{
    _pVector = new Vector[_iRows];
    for (int i = 0; i < _iRows; i++) { _pVector[i] = rMatrix._pVector[i]; }
}

Matrix& Matrix::operator=(const Matrix& rMatrix)
{
    if (this != &rMatrix)
    {
        if (0 != _pVector) { delete[] _pVector; pVector = 0; }
        _iRows = rMatrix._iRows;
        _iColumns = rMatrix._iColumns;
        _pVector = new Vector[_iRows];
        for (int i = 0; i < _iRows; i++) { _pVector[i] = rMatrix._pVector[i]; }
    }
    return *this;
}
Matrix& Matrix::operator+=(const Matrix& rMatrix)
{
    *this = *this + rMatrix;
    return *this;
}

Matrix Matrix::operator+(const Matrix& rMatrix) const
{
    Matrix matrix(_iRows, _iColumns);
    ValidateSizes(rMatrix);
    for (int i = 0; i < _iRows; i++) { matrix._pVector[i] = _pVector[i] + rMatrix._pVector[i]; }
    return matrix;
}

Matrix operator+(const Matrix& rMatrix, double dNum)
{
    Matrix matrix(rMatrix._iRows, rMatrix._iColumns);
    matrix.ValidateSizes(rMatrix);
    for (int i = 0; i < matrix._iRows; i++) { matrix._pVector[i] = dNum + rMatrix._pVector[i]; }
    return matrix;
}

Matrix operator+(double dNum, const Matrix& rMatrix)
{
    return operator+(rMatrix, dNum);
}

bool Matrix::ValidateSizes(const Matrix& rMatrix) const
{
    if (_iRows != rMatrix._iRows) { /* THROW EXCEPTION */ }
    if (_iColumns != rMatrix._iColumns) { /* THROW EXCEPTION */ }
    return true;
}
2 голосов
/ 08 декабря 2010

Если это матрица для 3D-рендеринга / симуляции, я бы НЕ рекомендовал динамически распределять память таким образом.Вы можете закончить с распределением памяти повсюду, что вызывает проблемы с кэшированием.Это также приводит к потенциальным ошибкам памяти.

template <typename T>
class Matrix
{
   public:
      T   m_Data[4][4];
};

или если вы хотите что-то не-4x4

template <typename T, unsigned int rows, unsigned int columns>
class Matrix
{
   public:
      T   m_Data[rows][columns];
};

, а затем динамически выделяете объекты Matrix.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...