2014 dxdy logo

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

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




Начать новую тему Ответить на тему
 
 c++ матрица через класс + перегрузка вывода
Сообщение09.06.2006, 22:40 
Аватара пользователя


24/10/05
400
у меня в программе нужно через констукторы класса инициализировать матрицу. Через перегрузку операции вывода вывести ее на экран.
У меня все компилируется, а при выполнении пишет ошибку.
Вот текст программы.
#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 


27/11/05
183
Северодонецк
В вашей программе, как минимум, две ошибки:

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 
Модератор
Аватара пользователя


11/01/06
5660
Несколько замечаний:

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 


27/11/05
183
Северодонецк
Уважаемый maxal!

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

 Профиль  
                  
 
 
Сообщение10.06.2006, 08:04 
Модератор
Аватара пользователя


11/01/06
5660
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 
Аватара пользователя


17/04/06
18
Хабаровск, ВЦ ДВО РАН
Мысли в слух.
Никогда не мог понять зачем люди пишут велосипеды. Ведь есть же, например, mtl, blas etc. И реализация там на достаточно высоком уровне. Но нет же - каждый пишет свой класс-контейнер даных. Неужели у этих людей нет больше задач, как писать то что уже сто раз написано...

 Профиль  
                  
 
 
Сообщение10.06.2006, 16:24 


27/11/05
183
Северодонецк
Так может автору программы такой преподаватель достался, что дает такие задания,
и это вовсе не программа из жизни?

 Профиль  
                  
 
 
Сообщение11.06.2006, 10:44 
Аватара пользователя


24/10/05
400
bekas писал(а):
Так может автору программы такой преподаватель достался, что дает такие задания,
и это вовсе не программа из жизни?

угадал.

 Профиль  
                  
 
 
Сообщение11.06.2006, 10:46 
Аватара пользователя


24/10/05
400
одну перегрузку исправил, теперь осталось перегрузить операцию +.
Опять непонятная ошибка

Код:
#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 


27/11/05
183
Северодонецк
Опять ошибка связана с передачей объекта по значению, а не по ссылке.
В результате удаления копии объекта вызывается деструктор, в котором
удаляется память, а потом еще раз по завершении 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 
Аватара пользователя


24/10/05
400
Переделал, разобрался в Шилдте,но все равно что-то в перегрузке "+" не так??
Код:
#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 


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

 Профиль  
                  
 
 
Сообщение28.03.2009, 20:09 


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

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group