2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 c++ матрица через класс + перегрузка вывода
Сообщение09.06.2006, 22:40 
Аватара пользователя
у меня в программе нужно через констукторы класса инициализировать матрицу. Через перегрузку операции вывода вывести ее на экран.
У меня все компилируется, а при выполнении пишет ошибку.
Вот текст программы.
#include <iostream.h>

class tagMatrix
{
int len;
int **matr;

public:
tagMatrix()
{
len=1;
matr = new int *[len + 1];
for(int i = 0; i < (len+1); i++)
matr[i] = new int[len+1];

for(i=0;i < (len+1); i++)
{
for(int j=0;j < (len+1); j++)
{
if (i==j) matr[i][j]=1;
else matr[i][j]=0;
}
}
}
tagMatrix(int );
friend ostream& operator << ( ostream& ,tagMatrix);
~tagMatrix()
{ delete matr; }
};


tagMatrix::tagMatrix(int len)
{
matr = new int *[len + 1];
for(int i = 0; i < (len+1); i++)
matr[i] = new int[len+1]; for(i=0;i < (len+1); i++)
{
for(int j=0;j < (len+1); j++)
{
if (i==j) matr[i][j]=1;
else matr[i][j]=0;
}
}



}

ostream& operator << ( ostream& out,tagMatrix matrix)
{ for (int i=0;i< matrix.len;i++)
{
for(int j=0; j< matrix.len;j++)
out << matrix.matr[i][j];
}




return out;

}

int main()
{
tagMatrix matrixx(3);
cout << matrixx;
return 0;
}

 
 
 
 
Сообщение09.06.2006, 23:56 
В вашей программе, как минимум, две ошибки:

1) конструктор tagMatrix::tagMatrix(int len) не устанавливает
значение len переменной класса, посмотрите конструктор
tagMatrix(), который устанавливает len=1;
Поэтому поведение цикла for (int i=0;i< matrix.len;i++) в
ostream& operator << (ostream& out,tagMatrix matrix) не определено.

2) так как в ostream& operator << (ostream& out,tagMatrix matrix)
объект класса передается по значению, то после завершения этой
функции будет вызван деструктор ~tagMatrix(), и кроме того,
по завершении программы main также повторно будет вызван деструктор
~tagMatrix(). А так как оба деструктора освобождают память (впрочем,
не совсем корректно, так как там остаются висячие ссылки на подмассивы),
то повторное освобождение уже освобожденной памяти влечет за собой
ошибку распределения памяти.

Для исправления проблемы 2) достаточно (ostream& out,tagMatrix &matrix),
а проблему 1) устраните сами. И не забудьте корректно определить
деструктор ~tagMatrix().

 
 
 
 
Сообщение09.06.2006, 23:58 
Аватара пользователя
Несколько замечаний:

1. Для программного кода есть специальный тэг [ code ] .... [ /code ] сохраняющий форматирование.

2. В паре мест пропущено опредение переменной цикла. Вместо
for(i=0;i < (len+1); i++)
должно быть
for(int i=0;i < (len+1); i++)

3. Непонятно зачем определяется матрица размера (len+1)x(len+1), особенно если потом в той же процедуре вывода используется только первые len строк и столбцов?

4. Второй параметр оператора << лучше определить как const tagMatrix&

5. В программе наблюдается утечка памяти в деструкторе ~tagMatrix(). Перед delete matr нужно осводить память по указателяем каждого элемента этого массива. Т.е. что-то типа
Код:
for (int i=0; i<(len+1);i++) delete matr[i];


6. А проблема у вас в том, что отсутствует инициализация члена класса len в конструкторе tagMatrix::tagMatrix(int len). Можно, например, первой строчкой в этом конструкторе поставить
Код:
this->len = len;

 
 
 
 
Сообщение10.06.2006, 07:37 
Уважаемый maxal!

Ваш пункт 2) не совсем справедлив. Во-первых, не в паре мест, а только в одном месте.
Во-вторых, в данном случае никакого криминала нет, так как выше переменная i
определена в предыдущем цикле, который уже сделал свое дело и не использует
эту переменную. А главной проблемой можно считать все же повторный вызов
деструктора, когда объект передается по значению, а не по ссылке. Хотя и отсутствие установки len тоже приятностей мало приносит...

 
 
 
 
Сообщение10.06.2006, 08:04 
Аватара пользователя
bekas писал(а):
Ваш пункт 2) не совсем справедлив. Во-первых, не в паре мест, а только в одном месте.

В двух - в конструкторе tagMatrix() и в конструкторе tagMatrix(int).
bekas писал(а):
Во-вторых, в данном случае никакого криминала нет, так как выше переменная i
определена в предыдущем цикле, который уже сделал свое дело и не использует
эту переменную.

Согласно последнему стандарту ISO C++, переменные объявленные внутри for() не должны быть видимы вне цикла.
Компилятор должен выдавать ошибку. Например, g++ 4.1 совершенно справедливо выдает:

t.cpp: In constructor 'tagMatrix::tagMatrix(int)':
t.cpp:38: error: name lookup of 'i' changed for new ISO 'for' scoping
t.cpp:36: error: using obsolete binding at 'i'

 
 
 
 
Сообщение10.06.2006, 15:15 
Аватара пользователя
Мысли в слух.
Никогда не мог понять зачем люди пишут велосипеды. Ведь есть же, например, mtl, blas etc. И реализация там на достаточно высоком уровне. Но нет же - каждый пишет свой класс-контейнер даных. Неужели у этих людей нет больше задач, как писать то что уже сто раз написано...

 
 
 
 
Сообщение10.06.2006, 16:24 
Так может автору программы такой преподаватель достался, что дает такие задания,
и это вовсе не программа из жизни?

 
 
 
 
Сообщение11.06.2006, 10:44 
Аватара пользователя
bekas писал(а):
Так может автору программы такой преподаватель достался, что дает такие задания,
и это вовсе не программа из жизни?

угадал.

 
 
 
 
Сообщение11.06.2006, 10:46 
Аватара пользователя
одну перегрузку исправил, теперь осталось перегрузить операцию +.
Опять непонятная ошибка

Код:
#include <iostream.h>

class tagMatrix
{
   int len;
   int **matr;

   public:
   tagMatrix() // edinichnaya matriza
      {
      len=2;
      matr = new int *[len];
      for(int i = 0; i < (len); i++)
      matr[i] = new int[len];

      for( i=0;i < (len); i++)
         {
            for(int j=0;j < (len); j++)
               {
               if (i==j) matr[i][j]=1;
               else matr[i][j]=0;
               }
         }
      }
   tagMatrix(int );
tagMatrix operator  +( tagMatrix );

   friend ostream& operator << ( ostream& ,tagMatrix &);
   
   
   ~tagMatrix()    { for (int i=0; i<(len);i++) delete matr[i]; }
   };


tagMatrix::tagMatrix(int len)
   {
       
      this->len = len;
      matr = new int *[len];
      for(int i = 0; i < (len); i++)
      matr[i] = new int[len+1];
      for(i=0;i < (len); i++)
         {
            for(int j=0;j < (len); j++)
                   
                     matr[i][j]=i+j;
               
         }
   }

ostream& operator << ( ostream& out,tagMatrix &matrix)
   {
   for (int i=0;i< matrix.len;i++)
      {
         for(int j=0; j< matrix.len;j++)
            {
               out<< matrix.matr[i][j]<<" ";   
             if (j == (matrix.len-1))
                out<< "\n";
            }
         
      }
    out <<"\n";
   return out;
   }
tagMatrix tagMatrix::operator +(tagMatrix t)
{

   tagMatrix t1(len);//poryadok matrizy
   for (int i=0;i< len;i++)
      {
         for(int j=0; j< len;  j++)
            {
            t1.matr[i][j]=    ((matr[i][j])+ (t.matr[i][j]));
            }
         
      }


return t1;
}
   


int main()
{
tagMatrix m1;
tagMatrix m2(3);
tagMatrix m3(3);
cout << m1;
cout << m2;
cout << m3;
cout<< m2+m3;
return 0;
}

 
 
 
 
Сообщение11.06.2006, 19:10 
Опять ошибка связана с передачей объекта по значению, а не по ссылке.
В результате удаления копии объекта вызывается деструктор, в котором
удаляется память, а потом еще раз по завершении main вызывается
соответствующий деструктор. Рекомендую тщательно разобраться,
в каких случаях вызывается деструктор, об этом говорится во многих
учебниках, возьмите, например, Самоучитель C++, Г. Шилдт.

Для исправления ошибки определите перегрузку "+" как

tagMatrix tagMatrix::operator +(tagMatrix &t)

И еще замечание по поводу деструктора: первый вариант программы
удалял память, занятую под массив ссылок, а сами ссылки оставались
неосвобожденными. Теперь же перекос в другую сторону:
ссылки освобождаются, а массив ссылок нет. Поэтому деструктор
должен выглядеть следующим образом:

Код:
~tagMatrix()
{
  for (int i=0; i<(len);i++)
    delete matr[i];
  delete matr;
}

 
 
 
 
Сообщение12.06.2006, 22:32 
Аватара пользователя
Переделал, разобрался в Шилдте,но все равно что-то в перегрузке "+" не так??
Код:
#include <iostream.h>

class tagMatrix
{
   int len;
   int **matr;

   public:
   tagMatrix(); // edinichnaya matriza
      
   tagMatrix(int );
   tagMatrix(int, int );
   tagMatrix(tagMatrix &);
    tagMatrix operator  +( tagMatrix &);
   friend ostream& operator << ( ostream& ,tagMatrix &);
   
   
   ~tagMatrix()
   {
      delete matr;
   for (int i=0; i<(len);i++)
    delete matr[i];
   
   
   }

   };
tagMatrix::tagMatrix()
{
      len=2;
      matr = new int *[len];
      for(int i = 0; i < (len); i++)
      matr[i] = new int[len];

      for( i=0;i < (len); i++)
         {
            for(int j=0;j < (len); j++)
               {
               if (i==j) matr[i][j]=1;
               else matr[i][j]=0;
               }
         }
      }

tagMatrix::tagMatrix(int len)
   {
      
      this->len = len;
      matr = new int *[len];
      for(int i = 0; i < (len); i++)
      matr[i] = new int[len+1];
      for(i=0;i < (len); i++)
         {
            for(int j=0;j < (len); j++)
                  
                     matr[i][j]=i+j;
               
         }
   }
tagMatrix::tagMatrix(int len, int num)
   {
      
      this->len = len;
      matr = new int *[len];
      for(int i = 0; i < (len); i++)
      matr[i] = new int[len+1];
      for( i=0;i < (len); i++)
         {
            for(int j=0;j < (len); j++)
               {
               if (i==j) matr[i][j]=num;
               else matr[i][j]=0;
               }
         }
   }
tagMatrix::tagMatrix(tagMatrix &o)
   {
       o.matr = new int *[o.len];
      for(int i = 0; i < (o.len); i++)
      o.matr[i] = new int[o.len+1];
      for(i=0;i < (o.len); i++)
         {
         for(int j=0;j < (o.len); j++)
         o.matr[i][j]=i+j;               
         }

      
   }


ostream& operator << ( ostream& out,tagMatrix &matrix)
   {
   for (int i=0;i< matrix.len;i++)
      {
         for(int j=0; j< matrix.len;j++)
            {
               out<< matrix.matr[i][j]<<" ";   
             if (j == (matrix.len-1))
                out<< "\n";
            }
         
      }
    out <<"\n";
   return out;
   }
tagMatrix tagMatrix::operator +(tagMatrix &t)

{
tagMatrix t1(this->len);//poryadok matrizy
   for (int i=0;i< (this->len);i++)
      {
         for(int j=0; j< (this->len);  j++)
            {
            t1.matr[i][j]=((matr[i][j])+ (t.matr[i][j]));
            }
         
      }


return t1;
}
   


int main()
{
tagMatrix m1;
tagMatrix m2(2);
tagMatrix m3(2,5);
cout << m1;
cout << m2;
cout << m3;

m2+m3;
return 0;
}

 
 
 
 
Сообщение13.06.2006, 20:29 
Помнится, лет двадцать пять тому назад, мы выясняли: какое самое главное
качество должно быть у программиста. Как ни странно, но многие сошлись на том,
что в первую очередь надо быть очень внимательным, а вовсе не иметь какой-нибудь запредельный уровень интеллектуальности. Смотрите мое предложение по
~tagMatrix() и как вы сами это реализовали. В программировании от перестановки
операторов очень даже многое меняется...

 
 
 
 
Сообщение28.03.2009, 20:09 
Можете написать правильный вариант перегрузки операции +, пожалуйста.
Интересует для случая: tagMatrix tagMatrix::operator +(tagMatrix &t)

 
 
 [ Сообщений: 13 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group