2014-01-24 1 views
0

Я хочу реализовать класс матрицы, который использует оператор [] [].не может передать значение const оператору +, которое использует оператор [] []

Я написал код, приведенные ниже, но проблема в том, что я не могу отправить константных значения оператору + !! (ошибка: передача «константную Матрицу», как «это» аргумент "Матрица :: индексатора Matrix :: Оператор сброшенной квалификаторы [-fpermissive])

Если я изменю его на матричный оператор + (Матрица & прочее); Он отлично работает ...

Я думаю, мне нужно две перегрузки матрицы :: Indexer Matrix :: operator [] (int index) для чтения и записи для mat_ (как свойство в C#!) Но как? !

или может быть я должен использовать const_cast?!

Каков наилучший способ реализации этого класса?!

//Matrix.h 
class Matrix 
{ 
public: 
    Matrix(const int rows, const int cols, float defaultValue=0); 
    //TODO copy constructor , destructor 

    int rows() const; 
    int cols() const; 


    Matrix operator+(const Matrix& other); 

    class Indexer 
    { 
    public: 
     Indexer(float* arr,int cols); 
     float& operator[](int index); 
    private: 
     float* arr_; 
     int cols_; 
    }; 

    Indexer operator[](int index); 

private: 
    int rows_; 
    int cols_; 
    float **mat_; 

}; 

Matrix.cpp

#include "matrix.h" 

Matrix::Matrix(const int rows, const int cols, float defaultValue) : 
    rows_(rows), 
    cols_(cols) 
{ 
    mat_=new float*[rows_]; 

    for(int i=0;i<rows;i++) 
    { 
     mat_[i]=new float[cols]; 
    } 

    for(int i=0;i<rows;i++) 
    { 
     for(int j=0;j<cols;j++) 
     { 
      mat_[i][j]=defaultValue; 
     } 
    } 

} 


int Matrix::rows() const 
{ 
    return rows_; 
} 
int Matrix::cols() const 
{ 
    return cols_; 
} 


Matrix::Indexer::Indexer(float* arr,int cols): 
    arr_(arr), 
    cols_(cols) 
{} 


Matrix::Indexer Matrix::operator[](int index) 
{ 
    if(index>=rows_) 
     throw "Out of row index"; 
    return Indexer(mat_[index],cols_); 
} 

float& Matrix::Indexer::operator[](int index) 
{ 
    if(index>=cols_) 
     throw "Out of cols index"; 
    return arr_[index]; 
} 

Matrix Matrix::operator+(const Matrix& other)//error 
{ 
    if(other.rows()!=this->rows()||other.cols()!=this->cols()) 
     throw "rows and cols are not equal"; 
    Matrix result(other.rows(),other.cols()); 
    for(int i=0;i<rows();i++) 
    { 
     for(int j=0;j<cols();j++) 
     { 
      result[i][j]=mat_[i][j]+other[i][j];//error: passing 'const Matrix' as 'this' argument of 'Matrix::Indexer Matrix::operator' discards qualifiers [-fpermissive 
     } 

    } 
    return result; 
} 
+0

@BrettHale Да. В нашем коде '[]' на матрице возвращает 'Row', который не содержит никаких данных сам по себе, а представляет собой представление подмножества данных матрицы. (У нас также есть представление столбца, но это может быть сложно реализовать.) –

+0

@BrettHale Матрица остается большой. Оба 'Row' и' Column' предоставляют представления (проекции) матрицы. –

+0

@BrettHale За исключением того, что в этом нет ничего, что является основным столбцом. Для n-мерной структуры данных существуют (по крайней мере) n проекций на одно измерение. Предоставление одного без предоставления всех из них - отсутствие ортогональности, мягко говоря. –

ответ

0

Я установил мою проблему, добавив

const Indexer operator[](int index)const; 

и

const float& operator[](int index)const; 

Мой код:

Matrix.h

#ifndef MATRIX_H 
#define MATRIX_H 

#include <iostream> 

class Matrix 
{ 
public: 
    Matrix(const int rows, const int cols, float defaultValue=0); 
    //TODO copy constructor , destructor 

    int rows() const; 
    int cols() const; 


    Matrix operator+(const Matrix& other) const; 

    class Indexer 
    { 
    public: 
     Indexer(float* arr,int cols); 
     const float& operator[](int index)const; 
     float& operator[](int index); 
    private: 
     float* arr_; 
     int cols_; 
    }; 

    Indexer operator[](int index); 
    const Indexer operator[](int index)const; 

    friend std::ostream& operator<<(std::ostream& os,const Matrix& m); 

private: 
    int rows_; 
    int cols_; 
    float **mat_; 
}; 

#endif // MATRIX_H 

Matrix.cpp

#include "matrix.h" 

Matrix::Matrix(const int rows, const int cols, float defaultValue) : 
    rows_(rows), 
    cols_(cols) 
{ 
    mat_=new float*[rows_]; 

    for(int i=0;i<rows;i++) 
    { 
     mat_[i]=new float[cols]; 
    } 

    for(int i=0;i<rows;i++) 
    { 
     for(int j=0;j<cols;j++) 
     { 
      mat_[i][j]=defaultValue; 
     } 
    } 

} 


int Matrix::rows() const 
{ 
    return rows_; 
} 
int Matrix::cols() const 
{ 
    return cols_; 
} 


Matrix::Indexer::Indexer(float* arr,int cols): 
    arr_(arr), 
    cols_(cols) 
{} 

const float &Matrix::Indexer::operator[](int index) const 
{ 
    if(index>=cols_) 
     throw "Out of cols index"; 
    return arr_[index]; 
} 


Matrix::Indexer Matrix::operator[](int index) 
{ 
    if(index>=rows_) 
     throw "Out of row index"; 
    return Indexer(mat_[index],cols_); 
} 

const Matrix::Indexer Matrix::operator[](int index) const 
{ 
    if(index>=rows_) 
     throw "Out of row index"; 
    return Indexer(mat_[index],cols_); 
} 

std::ostream& operator<<(std::ostream &os, const Matrix &m) 
{ 
    for(int i=0;i<m.rows();i++) 
    { 
     for(int j=0;j<m.cols();j++) 
     { 
      os<<m[i][j]<<" "; 
     } 
     os<<"\n"; 
    } 
    return os; 
} 

float& Matrix::Indexer::operator[](int index) 
{ 
    if(index>=cols_) 
     throw "Out of cols index"; 
    return arr_[index]; 
} 

Matrix Matrix::operator+(const Matrix& other) const 
{ 
    if(other.rows()!=this->rows()||other.cols()!=this->cols()) 
     throw "rows and cols are not equal"; 
    Matrix result(other.rows(),other.cols()); 
    for(int i=0;i<rows();i++) 
    { 
     for(int j=0;j<cols();j++) 
     { 
      result[i][j]=mat_[i][j]+other[i][j]; 
     } 

    } 
    return result; 
} 
2

Ваш operator+ должна быть константной функцией, так как она не изменяет объект он вызывается на. Для остальных вам, вероятно, понадобится ConstIndexer и operator[](int index) const.

И совершенно не связано с вашим вопросом, но: вам, вероятно, было бы лучше использовать std::vector<float> для получения фактических данных. Это проще в использовании и (возможно) быстрее.

Смежные вопросы