2013-11-18 7 views
5

Я пытаюсь определить простой класс для работы с матрицами 2d, называемый Matrix2D01, и иметь проблемы с оператором +. У меня есть + = оператор, который работает нормально,Как правильно перегрузить + оператор

Matrix2D01& Matrix2D01::operator+=(Matrix2D01& mat2) { 
    int i,j; 
    for (i=0;i<M;i++) 
     for (j=0;j<N;j++) mat[i][j]+=mat2[i][j]; 
return *this; 
} 

Оператор + определен:

Matrix2D01 Matrix2D01::operator+(Matrix2D01& mat2) { 
    Matrix2D01 result(1,1); 
    result=*this; 
    result+=mat2; 
    return result; 
} 

При попытке использовать оператор +, например, с помощью

mat3=mat1+mat2; 

компилятор дает сообщение об ошибке:

../MatrixGames.cpp:17:12: error: no match for ‘operator=’ in ‘mat3 = Matrix2D01::operator+(Matrix2D01&)((* & mat2))’ 

Если кто-нибудь скажет мне, что я делаю неправильно, мы будем очень благодарны.

Спасибо.

У меня также есть = оператор, определенный,

Matrix2D01& Matrix2D01::operator=(Matrix2D01& mat2) { 
    if (this==&mat2) return *this; 
    int i,j; 
    for (i=0;i<M;i++) { 
     delete [] mat[i]; 
    } 
    delete [] mat; 
    M=mat2.Dimensions()[0]; 
    N=mat2.Dimensions()[1]; 
    mat = new double* [M]; 
    for (i=0;i<M;i++) { 
     mat[i]=new double [N]; 
    } 
    for (i=0;i<M;i++) 
     for (j=0;j<M;j++) 
      mat[i][j]=mat2[i][j]; 
    return *this; 
} 

здесь полный тест:

#include <iostream> 
#include <stdlib.h> 
#include <stdio.h> 
#include <vector> 
using namespace std; 
class Matrix2D01 { 
protected: 
    int D; 
    double **mat; 
    int M,N; 
public: 
    Matrix2D01(int m,int n); 
    Matrix2D01(int m,int n,double d); 
    ~Matrix2D01(); 
    vector <int> Dimensions() {vector <int> d(D,M); d[1]=N; return d;} 
    double* operator[](int i) {return mat[i];} 
    Matrix2D01& operator=(Matrix2D01& mat2); 
    Matrix2D01& operator+=(Matrix2D01& mat2); 
    Matrix2D01 operator+(Matrix2D01& mat2); 
}; 
Matrix2D01::Matrix2D01(int m, int n) { 
    int i,j; 
    D=2; 
    M=m; 
    N=n; 
    mat = new double* [M]; 
    for (i=0;i<M;i++) { 
     mat[i]=new double [N]; 
    } 
    for (i=0;i<M;i++) 
     for (j=0;j<M;j++) 
      mat[i][j]=0; 
} 

Matrix2D01::Matrix2D01(int m, int n,double d) { 
    int i,j; 
    D=2; 
    M=m; 
N=n; 
mat = new double* [M]; 
for (i=0;i<M;i++) { 
    mat[i]=new double [N]; 
} 

for (i=0;i<M;i++) 
    for (j=0;j<M;j++) 
     mat[i][j]=d; 
} 

Matrix2D01::~Matrix2D01() { 
int i; 
    for (i=0;i<M;i++) { 
     delete [] mat[i]; 
    } 
    delete [] mat; 
} 
    Matrix2D01& Matrix2D01::operator=(Matrix2D01& mat2) { 
    if (this==&mat2) return *this; 
    int i,j; 
    for (i=0;i<M;i++) { 
     delete [] mat[i]; 
    } 
    delete [] mat; 
    M=mat2.Dimensions()[0]; 
    N=mat2.Dimensions()[1]; 
    mat = new double* [M]; 
    for (i=0;i<M;i++) { 
     mat[i]=new double [N]; 
    } 
    for (i=0;i<M;i++) 
     for (j=0;j<M;j++) 
      mat[i][j]=mat2[i][j]; 
    return *this; 
}  
    Matrix2D01& Matrix2D01::operator+=(Matrix2D01& mat2) { 
    int i,j,M2,N2; 
    M2=mat2.Dimensions()[0]; 
    N2=mat2.Dimensions()[1]; 
    if ((M!=M2)||(N!=N2)) { 
     cout<<"error: attempted to add non-matching matrices"; 
     return *this; 
    } 
    for (i=0;i<M;i++) 
     for (j=0;j<N;j++) mat[i][j]+=mat2[i][j]; 
    return *this; 
}  
    Matrix2D01 Matrix2D01::operator+(Matrix2D01& mat2) { 
    Matrix2D01 result(1,1); 
    result=*this; 
    result+=mat2; 
    return result; 
}  
    int main() { 
    Matrix2D01 mat1(2,2,1); 
    Matrix2D01 mat2(2,2,2); 
    Matrix2D01 mat3(2,2,4); 
    mat3+=mat1; 
    mat3=mat1+mat2; 
    return 1; 
} 
+0

связан этот вопрос http://stackoverflow.com/questions/4421706/operator-overloading/4421719#4421719 – jbat100

+0

Есть несколько проблем с этим кодом , Прежде всего: 'ח' не является допустимым символом в исходном коде C++. Тогда 'operator +' должен быть 'const', и либо принимать не ссылки, либо const-ссылки. Аналогично, 'operator + =' должен принимать не ссылки или const-ссылки. Можете ли вы также отправить полный тест? –

+0

'no match for 'operator ='' предполагает, что вы не определили оператор '=' для другого 'Matrix2D01' (возможно, существует еще один вид, удаляющий автоматический' = 'op), поэтому' mat1 + mat2' работает, но результат не может быть присвоен 'mat3'. Попробуйте создать 'Matrix2D01 & Matrix2D01 :: operator = (const Matrix2D01 и другие)'. – jozxyqk

ответ

1

Я разместил код класса Matrix я написал для назначения на Дискретная математика последний Семе

Обратите внимание, как реализованы оператор присваивания и конструктор копирования Все, что вам нужно сделать i напишем оператор присваивания (я рекомендовал бы, чтобы вы написали конструктор копирования, а)

#pragma once 

#include <vector> 
#include <istream> 
#include <ostream> 

class Matrix 
{ 
private: 
    unsigned int rows, cols; 
    std::vector<std::vector<int> > matrix; 

public: 
    // Creates a Matrix with the given dimensions and sets the default value of all the elements to 0 
    Matrix(unsigned int rows, unsigned int cols); 
    // Destructor 
    ~Matrix(); 

    // Converts the relation set into it's adjacency Matrix representation 
    static Matrix CreateFromRelationSet(std::vector<std::pair<int, int> > relationSet); 

    // Copy Constructor 
    Matrix(const Matrix& cSource); 
    // Assignment Operator 
    Matrix& operator=(const Matrix& cSource); 

    // Resets all the elements of the matrix to 0 
    void Reset(); 
    // Resizes the matrix to the given size 
    void Resize(unsigned int rows, unsigned int cols); 

    // Returns the number of rows 
    unsigned int getRows(); 
    // Returns the number of columns 
    unsigned int getCols(); 

    // Returns the smallest element from the matrix 
    int getSmallestElement(); 
    // Returns the greatest element from the matrix 
    int getGreatestElement(); 

    // Returns true if element is found and sets the row and column 
    // Returns false if not found 
    bool getPosition(int element, int* i, int* j); 

    // Deletes a row from the Matrix 
    void DeleteRow(unsigned int row); 
    // Deletes a column from the Matrix 
    void DeleteColumn(unsigned int col); 

    // Returns the element at (i,j) 
    int& operator()(unsigned int i, unsigned j); 
    // Returns the element at (i,j). Use the() operators instead 
    int getElementAt(unsigned int i, unsigned j); 

    friend std::ostream& operator << (std::ostream& out, Matrix& m); 
    friend std::istream& operator >> (std::istream& in, Matrix& m); 

    Matrix operator + (Matrix M); 
    Matrix operator - (Matrix M); 
    Matrix operator * (Matrix M); 
}; 

// For use with cin & cout 
std::ostream& operator << (std::ostream& out, Matrix& m); 
std::istream& operator >> (std::istream& in, Matrix& m); 


#include "Matrix.h" 

Matrix::Matrix(unsigned int rows, unsigned int cols) 
{ 
    this->rows = rows; 
    this->cols = cols; 

    matrix.resize(rows); 
    for(std::vector<int>& i: matrix) 
     i.resize(cols); 

    Reset(); 
} 

Matrix::~Matrix() 
{ 

} 

// local helper function 
int findMaxFromSet(std::vector<std::pair<int, int> > set) 
{ 
    int maxVal = 0; 
    for(unsigned int i = 0; i < set.size(); i ++) 
    { 
     int p = set[i].first > set[i].second ? set[i].first : set[i].second; 
     maxVal = maxVal > p ? maxVal : p; 
    } 

    return maxVal; 
} 

Matrix Matrix::CreateFromRelationSet (std::vector<std::pair<int, int> > relationSet) 
{ 
    int max = findMaxFromSet(relationSet); 
    Matrix M(max,max); 
    M.Reset(); 

    for(auto i = relationSet.begin(); i != relationSet.end(); ++ i) 
     M(i->first - 1, i->second - 1) = 1; 

    return M; 
} 

void Matrix::Reset() 
{ 
    for (auto& i: matrix) 
     for(auto& j: i) 
      j = 0; 
} 

void Matrix::Resize(unsigned int rows, unsigned int cols) 
{ 
    matrix.resize(rows); 
    for(auto& i:matrix) 
     i.resize(cols); 
} 

unsigned int Matrix::getRows() 
{ 
    return rows; 
} 

unsigned int Matrix::getCols() 
{ 
    return cols; 
} 

Matrix::Matrix(const Matrix& cSource) 
{ 
    rows = cSource.rows; 
    cols = cSource.cols; 
    matrix = cSource.matrix; 
} 

bool Matrix::getPosition(int element, int* i, int* j) 
{ 
    for(unsigned int ii = 0; ii < getRows(); ii ++) 
     for(unsigned int jj = 0; jj < getCols(); jj ++) 
      if(matrix[ii][jj] == element) 
      { 
       *i = ii; 
       *j = jj; 
       return true; 
      } 

    return false; 
} 

Matrix& Matrix::operator=(const Matrix& cSource) 
{ 
    // check for self-assignment 
    if (this == &cSource) 
     return *this; 

    if(this->getRows() < cSource.rows) 
    { 
     this->rows = cSource.rows; 
     this->matrix.resize(cSource.rows); 
    } 

    if(this->getCols() < cSource.cols) 
    { 
     this->cols = cSource.cols; 
     for(auto& i:this->matrix) 
      i.resize(cSource.cols); 
    } 

    for(unsigned int i = 0; i < rows; i++) 
     for(unsigned int j = 0; j < cols; j++) 
      this->matrix[i][j] = const_cast<Matrix&>(cSource)(i,j); 

    return *this; 
} 

std::ostream& operator << (std::ostream& out, Matrix& m) 
{ 
    for(auto& i: m.matrix) 
    { 
     for(auto& j: i) 
      out<<j<<'\t'; 
     out<<std::endl; 
    } 
    return out; 
} 

std::istream& operator >> (std::istream& in, Matrix& m) 
{ 
    for(auto& i: m.matrix) 
     for(auto& j: i) 
      in>>j; 
    return in; 
} 

Matrix Matrix::operator + (Matrix op) 
{ 
    // Find the rows and cols of the new matrix 
    unsigned int r = this->getRows() > op.getRows()?this->getRows():op.getRows(); 
    unsigned int c = this->getCols() > op.getCols()?this->getCols():op.getCols(); 

    // Create Matrices 
    Matrix A = *this; 
    Matrix B = op; 
    Matrix R(r,c); 

    // Assign values 
    for(unsigned int i = 0; i < A.rows; i++) 
     for(unsigned int j = 0; j < A.cols; j++) 
      R(i,j) = A(i,j) + B(i,j); 

    return R; 
} 

Matrix Matrix::operator - (Matrix op) 
{ 
    // Find the rows and cols of the new matrix 
    unsigned int r = this->getRows() > op.getRows()?this->getRows():op.getRows(); 
    unsigned int c = this->getCols() > op.getCols()?this->getCols():op.getCols(); 

    // Create Matrices 
    Matrix A = *this; 
    Matrix B = op; 
    Matrix R(r,c); 

    // Assign values 
    for(unsigned int i = 0; i < A.rows; i++) 
     for(unsigned int j = 0; j < A.cols; j++) 
      R(i,j) = A(i,j) - B(i,j); 

    return R; 
} 

Matrix Matrix::operator* (Matrix op) 
{ 
    Matrix A = *this; 
    Matrix B = op; 
    if(A.getCols() != B.getRows()) 
     throw std::exception("Matrices cannot be multiplied"); 

    Matrix M(A.getRows(), B.getCols()); 

    for(unsigned int i=0 ; i<A.getRows() ; i++) 
     for(unsigned int j=0 ; j<B.getCols() ; j++) 
      for(unsigned int k=0 ; k<B.getRows() ; k++) 
       M(i,j) = M(i,j) + A(i,k) * B(k,j); 

    return M; 
} 

int& Matrix::operator()(unsigned int i, unsigned j) 
{ 
    return matrix[i][j]; 
} 

int Matrix::getElementAt(unsigned int i, unsigned j) 
{ 
    return (*this)(i,j); 
} 

int Matrix::getSmallestElement() 
{ 
    int result = matrix[0][0]; 
    for(auto i:matrix) 
     for(auto j : i) 
      if(j < result) 
       result = j; 
    return result; 
} 

int Matrix::getGreatestElement() 
{ 
    int result = matrix[0][0]; 
    for(auto i:matrix) 
     for(auto j : i) 
      if(j > result) 
       result = j; 
    return result; 
} 

void Matrix::DeleteRow(unsigned int row) 
{ 
    matrix.erase(matrix.begin() + row); 
    rows --; 
} 

void Matrix::DeleteColumn(unsigned int col) 
{ 
    for(auto& i: matrix) 
     i.erase(i.begin() + col); 
    cols --; 
} 

UPDATE:

result=*this; 

В своем коде вы пытаетесь выделить result значение *this с помощью оператор присваивания, но оператор присваивания не задан, а компилятор не нашел соответствия
Написание перегрузки оператора присваивания решит эту проблему.

И если у вас есть конструктор копирования вы можете сделать что-то вроде:

Matrix2D01 Matrix2D01::operator+(Matrix2D01& mat2) { 
    Matrix2D01 result = *this; 
    result+=mat2; 
    return result; 
} 

Написание операторов присваивания: http://www.learncpp.com/cpp-tutorial/912-shallow-vs-deep-copying/
И если вы заинтересованы в деталях - здесь вы идете: http://www.icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html

+0

Спасибо! ----------- :) – user3004480

+0

Было бы неплохо узнать, что не так с моим кодом, хотя .. – user3004480

+0

@ user3004480 У вас нет оператора присваивания, определенного вашим «Matrix2D01» class – gldraphael

1

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

Если ваш operator+ является членом, она должна быть константной, а также. В конце концов, он не изменяет объект, на который он вызван.Итак:

Matrix2D01& Matrix2D01::operator=(Matrix2D01 const& mat2); 
Matrix2D01& Matrix2D01::operator+=(Matrix2D01 const& mat2); 
Matrix2D01 Matrix2D01::operator+(Matrix2D01 const& mat2) const; 

Кроме того, ваш оператор назначения неисправен. (Подумайте, как произойдет , если одно из распределений завершится неудачей после того, как вы освободите исходные данные .) В общем случае, если вам нужно проверить для себя назначение , оператор присваивания нарушен.

2

Herb Sutter выступает the following canonical way to overload operator + (пожалуйста, прочитайте GotW, это действительно хорошо написано и интересно):

  • Не включайте operator + в качестве функции члена, вместо того, чтобы сделать это бесплатно функция.
  • Передайте один объект по значению, а другой - по ссылке const. Это позволяет использовать операторы перемещения при добавлении к временному.
  • Реализовать с точки зрения operator +=:

    Matrix2D01 operator+(Matrix2D01 a, const Matrix2D01 &b) 
    { 
        a += b; 
        return a; 
    } 
    
Смежные вопросы