Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.06.14;
Скачать: CL | DM;

Вниз

Что возвратить, если функция возвращает ссылку... ?   Найти похожие ветки 

 
Vulko ©   (2005-05-18 12:51) [0]

Есть перегрузка оператора для класса.
Класс диманической 2-мерной матрицы.

Оператор + суммирует 2 матрицы, если они одинаковых размеров.
Однако если они не одинаковых размеров, то не понятно что возвращать?

Пока решил возвращать *this, но ясно дело что это неприемлимо для данной задачи...


 Array2D &Array2D::operator+(const Array2D &arr)
  {
   int i, j, k, l;
   GetSize(i, j);
   arr.GetSize(k, l);
   if (i == k && j == l)
    {
     Array2D *tmp = new Array2D(i, j);
      for (i = 0; i < k; i++)
       for (j = 0; j < l; j++)
        tmp->push( i, j, pop(i, j) + arr.pop(i, j) );
     return *tmp;
    }
   else return *this; // Что тут возвращать???
  }


 
wal ©   (2005-05-18 12:53) [1]

Исключение, например, возбудить


 
VMcL ©   (2005-05-18 13:00) [2]

... или вернуть null.


 
VMcL ©   (2005-05-18 13:00) [3]

>>VMcL ©   (18.05.05 13:00) [2]

Упс, не заметил "&".


 
Vulko ©   (2005-05-18 13:03) [4]

wal, это понятное дело можно. Но возвратить надо какой-то объект типа класса (Array 2D). :)


 
Vulko ©   (2005-05-18 13:05) [5]

VMcL, вот хорошо бы, но никак...

На крайняк выдавать не ссылку, а нулевой указатель. Но не хотелось бы решать этот вопрос таким образом...


 
wicked ©   (2005-05-18 13:05) [6]

опреатор + лучше делать другом класса и возвращать, соответственно, новый экземпляр класса... так умные люди из boost.org советуют...


 
wicked ©   (2005-05-18 13:07) [7]

или вариант - поглядеть, как это делает blitz++... правда, это высший пилотаж... ;)


 
raidan ©   (2005-05-18 13:11) [8]

Удалено модератором
Примечание: Глубокие мысли - это железные гвозди, вогнанные в ум так, что ничем не вырвать их. /Д. Дидро/ (AutoModerator)


 
Vulko ©   (2005-05-18 13:12) [9]

wicked, ну понятно что можно сделать friend функцию.
Но хотелось бы без этого.

А что за blitz++ ? И как и что он делает?


 
Vulko ©   (2005-05-18 13:15) [10]

raidan, да да! именно такой!))


 
Vulko ©   (2005-05-18 14:12) [11]

Что такое blitz++ я понял.

Скачал. Посмотрел всё что связано с array"ами. Ничего не нашёл. Точнее может и смог бы, но результатов поиска под 1000 в исходнике...

Может кто навёд, где смотреть на этот "высший пилотаж"?


 
chii   (2005-05-18 14:45) [12]

Т.е. вы создаете объект в куче и возвращаете ссылку на него. ИМХО, с арихитектурной точки зрения это неправильно, тк динамически созданный объект подразумевает под собой удаление. Работая со ссылкой на динамический объект вы рискуете забыть об этом, что не есть хороший стиль. В данном случае, будет правильнее возвращать либо указатель, что абсурдно, либо объект по значению (для чего нужен конструктор копирования), создавая результат в стеке. Если вы хотите возврашать ссылку, вам нужно позаботиться о сборке мусора. Можно возвращать просто единичную матрицу (по значению). А более правильно, вызывать исключение. Все ИМХО.


 
Igorek ©   (2005-05-18 15:47) [13]

Vulko ©   (18.05.05 12:51)
1) вынеси операцию аллокации памяти отдельно
2) добавь конструктор копирования
3) определи +=
4) определи + через += используя статическую переменную в стеке


 
Polevi ©   (2005-05-18 16:15) [14]

исключение, однозначно


 
Vulko ©   (2005-05-18 19:03) [15]

Igorek, а зачем определять +=. Оно конечно хорошо, но по идее в можно написать a=a+b в перегрузке данного оператора... Так что особого смысла нету. Да и не подразумевается данный класс как исзуемый в дальнейшем.

Исключение конечно хорошо, но это значит прерывание работы программы. А это всё-таки нехорошо... Но в принципе как вариант подходит.

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

Буду рад, если объясните.

Код:

class Array2D
 {
   double **base;
   int columnSize;
   int rowSize;
  public:
   Array2D(int arrayColumnSize, int arrayRowSize); //&#202;&#238;&#237;&#241;&#242;&#240;&#243;&#234;&#242;&#238;&#240;
   ~Array2D(); //&#196;&#229;&#241;&#242;&#240;&#243;&#234;&#242;&#238;&#240;
   void push(int, int, double psh); // &#194;&#226;&#238;&#228;
   double pop(int i, int j) const; // &#194;&#251;&#226;&#238;&#228;
   void GetSize(int &n, int &m) const; // &#194;&#251;&#226;&#238;&#228; &#240;&#224;&#231;&#236;&#229;&#240;&#238;&#226; &#236;&#224;&#242;&#240;&#232;&#246;&#251;
   Array2D &operator=(const Array2D &arr); // &#207;&#240;&#232;&#241;&#226;&#224;&#232;&#226;&#224;&#237;&#232;&#229;
   Array2D &operator+(const Array2D &arr); // &#209;&#243;&#236;&#236;&#232;&#240;&#238;&#226;&#224;&#237;&#232;&#229;
   Array2D &operator-(const Array2D &arr); // &#194;&#251;&#247;&#232;&#242;&#224;&#237;&#232;&#229;
   Array2D &operator*(const Array2D &arr); // &#211;&#236;&#237;&#238;&#230;&#229;&#237;&#232;&#229;
 };

// &#202;&#238;&#237;&#241;&#242;&#240;&#243;&#234;&#242;&#238;&#240; &#238;&#225;&#250;&#229;&#234;&#242;&#238;&#226; &#234;&#235;&#224;&#241;&#241;&#224;
 Array2D::Array2D(int arrayColumnSize, int arrayRowSize)
  {
   base = new double*[arrayColumnSize];
    for ( int i = 0; i < arrayColumnSize; ++i )
     base[i] = new double[arrayRowSize];
   rowSize = arrayRowSize;
   columnSize = arrayColumnSize;
    for ( int i = 0; i < columnSize; ++i )
     for ( int j = 0; j < rowSize; ++j )
      base[i][j] = 0;
  }

// &#196;&#229;&#241;&#242;&#240;&#243;&#234;&#242;&#238;&#240; &#238;&#225;&#250;&#229;&#234;&#242;&#238;&#226; &#234;&#235;&#224;&#241;&#241;&#224;
 Array2D::~Array2D()
  {
   for ( int i = 0; i < columnSize; ++i )
    delete[] base[i];
   delete[] base;
  }

// &#194;&#226;&#238;&#228; [i, j]-&#242;&#238;&#227;&#238; &#253;&#235;&#229;&#236;&#229;&#237;&#242;&#224; &#236;&#224;&#241;&#241;&#232;&#226;&#224;
 void Array2D::push(int i, int j, double psh)
  {
   base[i][j] = psh;
  }

// &#194;&#251;&#226;&#238;&#228; [i, j]-&#242;&#238;&#227;&#238; &#253;&#235;&#229;&#236;&#229;&#237;&#242;&#224; &#236;&#224;&#241;&#241;&#232;&#226;&#224;
 double Array2D::pop(int i, int j) const
  {
   return base[i][j];
  }

// &#194;&#251;&#226;&#238;&#228; &#240;&#224;&#231;&#236;&#229;&#240;&#238;&#226; &#236;&#224;&#242;&#240;&#232;&#246;&#251;
 void Array2D::GetSize(int &n, int &m) const
  {
   m = columnSize;
   n = rowSize;;
  }

// &#207;&#240;&#232;&#241;&#226;&#224;&#232;&#226;&#224;&#237;&#232;&#229;
 Array2D &Array2D::operator=(const Array2D &arr)
  {
   int i, j, k, l;
   GetSize(i, j);
   arr.GetSize(k, l);
   if (i == k && j == l)
    for (i = 0; i < k; i++)
     for (j = 0; j < l; j++)
      push( i, j, arr.pop(i, j) );
   return *this;
  }

// &#209;&#243;&#236;&#236;&#232;&#240;&#238;&#226;&#224;&#237;&#232;&#229;
 Array2D &Array2D::operator+(const Array2D &arr)
  {
   int i, j, k, l;
   GetSize(i, j);
   arr.GetSize(k, l);
   if (i == k && j == l)
    {
     Array2D *tmp = new Array2D(i, j);
      for (i = 0; i < k; i++)
       for (j = 0; j < l; j++)
        tmp->push( i, j, pop(i, j) + arr.pop(i, j) );
     return *tmp;
    }
   else return *this;
  }

// &#194;&#251;&#247;&#232;&#242;&#224;&#237;&#232;&#229;
 Array2D &Array2D::operator-(const Array2D &arr)
  {
   int i, j, k, l;
   GetSize(i, j);
   arr.GetSize(k, l);
   if (i == k && j == l)
    {
     Array2D *tmp = new Array2D(i, j);
      for (i = 0; i < k; i++)
       for (j = 0; j < l; j++)
        tmp->push( i, j, pop(i, j) - arr.pop(i, j) );
     return *tmp;
    }
   else return *this;
  }

// &#211;&#236;&#237;&#238;&#230;&#229;&#237;&#232;&#229;
 Array2D &Array2D::operator*(const Array2D &arr)
  {
   int i, j, k, l, ii, jj, kk;
   GetSize(i, j);
   arr.GetSize(k, l);
   if (j == k)
    {
     Array2D *tmp = new Array2D(i, l);
      for(ii = 0; ii < i; ii++)
        for(jj = 0; jj < j; jj++)
         for(kk = 0; kk < l; kk++)
          tmp->push(ii, kk, tmp->pop(ii, kk) + pop(ii, jj)*arr.pop(jj, kk) );
     return *tmp;
    }
   else return *this;
  }


 
марсианин ©   (2005-05-19 02:13) [16]

убивец.. так никто не пишет
т.е. написать так можно - но это все равно, что удалять гланды ректально :)

по ссылке естественно возвращать себя..
поэтом результатом operator= является ссылка
Array2D &operator=(const Array2D &arr) { бла-бла-бла, return *this;}
Array2D &operator+=(const Array2D &arr); // &#207;&#240;&#232;&#241;&#226;&#224;&#232;&#226;&#224;&#237;&#232;&#229;

но когда создается новая переменная -- логично возвращать по значению.

например:
   Array2D Array2D::operator*(const Array2D &arr) const;

легко и просто.. правда придется определить копирующий конструктор

и еще..используй std::vector!!
кстати, еще valarray -  полезная штука.. как раз для матриц.


 
Igorek ©   (2005-05-19 11:11) [17]

Vulko ©   (18.05.05 19:03) [15]
Да и не подразумевается данный класс как исзуемый в дальнейшем.

С таким подходом тебе светит 3 и не более. 8-)
Vulko ©   (18.05.05 19:03) [15]
Igorek, а зачем определять +=. Оно конечно хорошо, но по идее в можно написать a=a+b в перегрузке данного оператора...

Наоборот. += эффективнее = + когда один из операндов тот же, что и lvalue.
Короче в лом обьяснять - читай Страутсрупа.

марсианин ©   (19.05.05 2:13) [16]
и еще..используй std::vector!!

Vulko не слушай его. Тебе надо самому реализовать с нуля.

Vulko ©   (18.05.05 19:03) [15]
Исключение конечно хорошо, но это значит прерывание работы программы. А это всё-таки нехорошо...

Ну а что ты хочешь? Несовместимые матрицы в операции. Ты можешь конечно использовать шаблон с размерами матрицы - тогда компилятор отловит ошибки. Но тогда будут только матрицы константных размеров.
template <int m, int n> class Array2D {
..
Array2D() {/*выделить память m на n*/}
};
..
typedef Array2D<5,5> matrix5x5;//чисто для удобства
typedef Array2D<2,3> matrix2x3;//чисто для удобства
matrix5x5 m1, m2;
matrix2x3 m3 = m1;//ошибка компиляции, разные типы
m1 = m2;//Ок
int M = 5, N = 5;//также могут вычисляться где-то
Array2D<M, N> m4;//ошибка, M,N - не константы

--
Все таки напиши лабу по человечески - потом сам себе благодарен будешь.


 
Vulko ©   (2005-05-22 22:04) [18]

Спасибо за ответы.

Igorek, по поводу написания человеческой лабы - была бы тема интересная, я бы с радостью. А за это итак поставят 5...
Просто на первом курсе у нас лабы примитивнейшие. Зато матан и га - засада. По матану зачёт сдать, это просто чудо. А по га экзамен сдать сложно, т.к. препод злой. Халява не прокатывает у него :) Нужно понимать и знать весь материал...


 
марсианин ©   (2005-05-23 01:29) [19]

это чего, у вас такая лаба? достичь желаемого самым хитрозадым способом?
это не есть правильная жизненная позицыя :)


> template <int m, int n> class Array2D {
> ..
> Array2D() {/*выделить память m на n*/}
> };

да, шаблоны -- мощная вещь!..
но при таком подходе совсем необязательно выделять память и пользоваться динамическими переменными.. :)

напр. так:
template <size_t m, size_t n>
struct Array2D
{
 double array[m][n];
 Array2D()
 {
   // /*выделить память m на n*/  - не нужно!
    for (size_t i = 0; i < m; ++i)
    for (size_t j = 0; j < n; ++j)
       array[i][j] = 0;  // обнулить все
 }
 Array2D& operator+=(const Array2D& a)
 {
    for (size_t i = 0; i < m; ++i)
    for (size_t j = 0; j < n; ++j)
        array[i][j] += a.array[i][j];
    return *this;
 }

 Array2D operator+(const Array2D& a) const
 {
    Array2D temp = *this;
    return temp +=  a;
 }
 //можно написать даже такое:
 Array2D<m,k> operator*(const Array2D<n,k>& a) const
 {
    Array2D<m,k> temp;
    for (size_t i = 0; i < m; ++i)
    for (size_t j = 0; j < k; ++j)
         for (size_t s = 0; s < n; ++s)
               temp[i][j] += array[i][s]*a.array[s][j];
   return temp;
 }
// operator= и копирующий конструктор - по умолчанию..
};


ИМХО, неудачное место для использования динамической памяти


 
Igorek ©   (2005-05-23 14:24) [20]

марсианин ©   (23.05.05 1:29) [19]
но при таком подходе совсем необязательно выделять память и пользоваться динамическими переменными.. :)

да, погнал я чуток :shuffle:

У тебя неточность:
>  Array2D<m,k> operator*(const Array2D<k,n></* а не n,k*/>& a) const



Страницы: 1 вся ветка

Текущий архив: 2005.06.14;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.049 c
14-1116679881
lookin
2005-05-21 16:51
2005.06.14
Сверхмилая фотография


14-1116917122
Layner
2005-05-24 10:45
2005.06.14
Яндекс.Деньги ворует деньги


1-1117183840
juice
2005-05-27 12:50
2005.06.14
try ... except ... finally


3-1115612624
Lex_!
2005-05-09 08:23
2005.06.14
Сохранение изображения в базе Access


1-1117453922
Ольга
2005-05-30 15:52
2005.06.14
Добавить пролог в XML-файл