Форум: "Потрепаться";
Текущий архив: 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); //Êîíñòðóêòîð
~Array2D(); //Äåñòðóêòîð
void push(int, int, double psh); // Ââîä
double pop(int i, int j) const; // Âûâîä
void GetSize(int &n, int &m) const; // Âûâîä ðàçìåðîâ ìàòðèöû
Array2D &operator=(const Array2D &arr); // Ïðèñâàèâàíèå
Array2D &operator+(const Array2D &arr); // Ñóììèðîâàíèå
Array2D &operator-(const Array2D &arr); // Âû÷èòàíèå
Array2D &operator*(const Array2D &arr); // Óìíîæåíèå
};
// Êîíñòðóêòîð îáúåêòîâ êëàññà
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;
}
// Äåñòðóêòîð îáúåêòîâ êëàññà
Array2D::~Array2D()
{
for ( int i = 0; i < columnSize; ++i )
delete[] base[i];
delete[] base;
}
// Ââîä [i, j]-òîãî ýëåìåíòà ìàññèâà
void Array2D::push(int i, int j, double psh)
{
base[i][j] = psh;
}
// Âûâîä [i, j]-òîãî ýëåìåíòà ìàññèâà
double Array2D::pop(int i, int j) const
{
return base[i][j];
}
// Âûâîä ðàçìåðîâ ìàòðèöû
void Array2D::GetSize(int &n, int &m) const
{
m = columnSize;
n = rowSize;;
}
// Ïðèñâàèâàíèå
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;
}
// Ñóììèðîâàíèå
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;
}
// Âû÷èòàíèå
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;
}
// Óìíîæåíèå
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); // Ïðèñâàèâàíèå
но когда создается новая переменная -- логично возвращать по значению.
например:
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.041 c