Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2005.06.14;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.037 c
4-1114276037
Виталик
2005-04-23 21:07
2005.06.14
Вопрос по логону.


1-1117339257
Homa_Programer
2005-05-29 08:00
2005.06.14
Popup &amp; DBGrid


6-1111871948
Nes
2005-03-27 00:19
2005.06.14
Undeclared identifier: TIdSocketHandle -- "Ха"?


4-1114413798
tradakad
2005-04-25 11:23
2005.06.14
какой лучше ипользовать метод вызова dll?


1-1117192435
Jupiter
2005-05-27 15:13
2005.06.14
Копирование по маске





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский