2012-02-19 5 views
3

Я пытаюсь создать перегруженный оператор для класса матрицы, который я создал. Мой матричный класс хранит матрицу в динамически распределенном многомерном массиве. Я просто пытаюсь проверить мой перегруженный оператор, умножив вместе две матрицы, которые будут точно такими же и отобразить вывод. Я получаю странные результаты, и я считаю, что это связано с одним из условных выражений на моих циклах. Однако я прошел через все мои петли и не могу найти ничего плохого. Матрицы, которые я умножаю вместе, равны 6х6.Матричное умножение с перегрузкой оператора

Мой перегруженный оператор

template <typename T> 
const matrix<T> matrix<T>::operator * (const matrix& right) const 
{ 
    matrix<T> c = right; 
    int sum_elems; 
    for(int i = 0; i < this->rows - 1; ++i) 
    { 
     for(int j = 0; j < right.cols - 1; ++j) 
     { 
      sum_elems = 0; 
      for(int k = 0; k < right.rows - 1; ++k) 
      { 
       sum_elems += this->the_matrix[i][k] * right.the_matrix[k][j]; 
      } 

      c.the_matrix[i][j] = sum_elems; 
     } 
    } 
    return c; 
}     

Теперь мой вызов перегруженного оператора в моей главной функции:

std::cout << my_matrix; 
matrix<int> copy_matrix; 
copy_matrix = my_matrix * my_matrix; 
std::cout << copy_matrix; 

Мой выход:

The Matrix: 
0 1 0 1 1 0 
1 0 1 0 1 1 
0 1 0 1 0 1 
1 0 1 0 1 0 
1 1 0 1 0 1 
0 1 1 0 1 0 
    The Matrix: 
-1 33 139587680 18 38 75 
139587680 18 38 75 157 1 
139587712 38 1470 4365 10411 1 
139587744 75 4365 19058932 64514866 0 
139587776 157 10411 64514866 1136204102 1 
139596144 1 1 0 1 0 

Как вы можете видеть, кажется, что я выхожу за пределы одного из своих массивов. Кажется, я не могу найти, где. Я ценю вашу помощь заранее.

Edit: В соответствии с просьбой моего полного осуществления моей матрицей класса

Матрица Определения:

template <typename T> 
class matrix 
{ 
    public: 

     //Default Constructor 
     matrix(); 

     //Overloaded Constructor 
     matrix(std::ifstream&, const char*); 

     //Copy Constructor 
     matrix(const matrix&); 

     //Destructor 
     ~matrix(); 


     //overloaded operators 
     T* operator [] (T); 
     const matrix operator * (const matrix&) const; 
     matrix& operator = (const matrix&); 
     friend std::ostream& operator << <T> (std::ostream&, const matrix<T>&); 


    private: 
     T** the_matrix; 
     unsigned rows, cols; 

Matrix Реализация:

/* Template version of matrix class */ 
/*---------------------------------------------------------------------------*/ 
// Default contructor 
template <typename T> 
matrix<T>::matrix() { } 

// Overloaded contructor 
template <typename T> 
matrix<T>::matrix(std::ifstream& in, const char* file) 
{ 

    // declare the variables to be used 
    T vertices, edges, u, v; 
    std::string line; 

    // open file for reading 
    in.open(file); 

    // get number of vertices 
    in >> vertices; 


    // throw away second line 
    std::getline(in, line); 
    std::getline(in, line); 

    // get number of edges and dump them in two arrays 
    in >> edges; 
    T edge1 [edges]; 
    T edge2 [edges]; 
    int j = 0, k = 0; 
    for(int a = 0; a < edges; ++a) 
    {  
     in >> u >> v; 
     edge1[j] = u; 
     edge2[k] = v; 
     ++j; 
     ++k; 
    } 

    in.close(); 

    // Create multi-dim-dynamic array 
    rows = vertices; 
    cols = vertices; 

    the_matrix = new T*[rows]; 

    for(int b = 0; b < rows; ++b) 
    { 
     the_matrix[b] = new T [rows]; 
    } 

    // Initialize array values to zero 
    for (int c = 0; c < rows; ++c) 
    { 
     for(int d = 0; d < cols; ++d) 
     { 
      the_matrix[c][d] = 0; 
     } 
    } 

    // push the edges to the matrix 
    for(int e = 0; e < edges; ++e) 
    { 
     the_matrix[edge1[e] - 1][edge2[e] - 1] = 1; 
    } 
    for (int f = 0; f < edges; ++f) 
    { 
     the_matrix[edge2[f] - 1][edge1[f]-1] = 1; 
    } 


} 

// Copy Constructor 
template <typename T> 
matrix<T>::matrix(const matrix& left) 
{ 
    the_matrix = left.the_matrix; 
    rows = left.rows; 
    cols = left.cols; 
    spath = left.spath; 
} 

// Destructor 
template <typename T> 
matrix<T>::~matrix() 
{ 
    // Deletes the data in reverse order of allocation 
    for(int a = cols; a > 0; --a) 
    { 
     delete[ ] the_matrix[a]; 
    } 

    delete[ ] the_matrix; 
} 

// Overloaded * Operator 
template <typename T> 
const matrix<T> matrix<T>::operator * (const matrix& right) const 
{ 
    matrix<T> c = right; 
    T sum_elems; 
    for(int i = 0; i < this->rows - 1; ++i) 
    { 
     for(int j = 0; j < right.cols - 1; ++j) 
     { 
      sum_elems = 0; 
      for(int k = 0; k < right.rows - 1; ++k) 
      { 
       sum_elems += this->the_matrix[i][k] * right.the_matrix[k][j]; 
      } 

      c.the_matrix[i][j] = sum_elems; 
     } 
    } 
    return c; 
} 

// Overloaded assignment Operator 
template <typename T> 
matrix<T>& matrix<T>::operator = (const matrix& right) 
{ 
    this->the_matrix= right.the_matrix; 
    this->rows = right.rows; 
    this->cols = right.cols; 
    this->spath = right.spath; 
    return *this; 
} 

// Overloaded << operator 
template <typename T> 
std::ostream& operator << (std::ostream& output, const matrix<T>& left) 
{ 
    // Test screen output to see if correct 
    std::cout << std::setw(14) << "The Matrix:" << '\n'; 
    for(int a = 0; a < left.rows; ++a) 
    { 
     for(int b = 0; b < left.cols; ++b) 
     { 
      std::cout << ' ' << left.the_matrix[a][b] << ' '; 
     } 
     std::cout << '\n'; 
    } 
    return output; 
} 
+0

Правильно ли копируется ваш матричный класс? Как в конструкторе копирования, так и в операторе присваивания? Вы говорите, что используете «динамически распределенный многомерный массив». Означает ли это, что вы вручную управляете своей памятью с помощью 'new' и' delete', а не с помощью вектора? Если да, то почему? –

+0

Оператор копирования и оператор присваивания работают безупречно.Я не использую 'vector' специально, потому что я пытаюсь узнать больше об использовании оператора' new' и 'delete' и вручную управлять памятью, а не всегда полагаться на' vector' для работы за кулисами. –

ответ

6

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

Исправьте эти функции, чтобы они фактически распределяли новые массивы и копировали данные.

+0

Вы абсолютно правы. Я не понимал, что просто делаю копию указателей. Как только я исправил оператор копирования и присваивания, мой * оператор работает отлично. Спасибо за вашу помощь! –

1
  1. i фактически идет от 0 до this->rows - 2 (из-за i < n-1 для i = n-1 является ложным). То же самое для других петель. Это, похоже, не правильное поведение для умножения матриц.
  2. Тем не менее, этот фрагмент кода кажется правильным. Можете ли вы предоставить нам полную реализацию класса?

P.S. Если T - тип матричных элементов, то тип sum_elems должен быть T.

+0

Я добавил полную реализацию по вашему запросу –

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