Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Перегрузка операций вычитания и смены знака с матр


Автор: astilla 20.1.2007, 14:32
Никак не могу сообразить, как сделать переграузку операции "смена знака" у матриц.
перегрузку операции вычитания сделала, но вот что интересно получается
Если использую такой код

Код

// операция вычитания A-B
Mtrx& Mtrx::operator-(Mtrx& Op2) {
   if ((m != Op2.m) & (n != Op2.n)) {
      cout << "Массивы имет разную размерность" << endl;
      exit(1);
   }
   Mtrx &C = *(new Mtrx (m,n));
   for(int i=0, j; i < m; i++)
     for(j=0; j < n; j++) 
       C.matr[i*m+j] = matr[i*m+j] - Op2.matr[i*m+j];
   return C;
}


то все правильно вычитается, то смена знака не получается
а если такой
Код

// операция вычитания A-B
Mtrx& Mtrx::operator-(Mtrx& Op2) {
   if ((m != Op2.m) & (n != Op2.n)) {
      cout << "Массивы имет разную размерность" << endl;
      exit(1);
   }
   Mtrx &C = *(new Mtrx (m,n));
   for(int i=0, j; i < m; i++)
     for(j=0; j < n; j++) 
       C(i,j)=C(i,j)-Op2(i,j);
   return C;
}

то "автоматически" получается "смена знака"

Как правильно мне написать перегрузку этих операций?

Автор: GIK 20.1.2007, 14:41
Цитата

C(i,j)=C(i,j)-Op2(i,j);

Эт че такое то, через указатель что вызываешь? Кидай полный код.

Автор: Rockie 20.1.2007, 14:44
Цитата(astilla @  20.1.2007,  14:32 Найти цитируемый пост)
 if ((m != Op2.m) & (n != Op2.n)) {

тут логическое или, как понимаю 
Код

||


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

1 -2
-3 4

Добавлено @ 14:49 
astilla, если только для положительных матриц, то перегружай оператор -- и вычитай из матрицы
Код

 C.matr[i*m+j] = C.matr[i*m+j]- C.matr[i*m+j]*2;



Автор: Anikmar 20.1.2007, 14:52
Цитата(astilla @  20.1.2007,  14:32 Найти цитируемый пост)
Никак не могу сообразить, как сделать переграузку операции "смена знака" у матриц

Я бы не парился, оператор- оставил бы для вычитания матриц, а для смены знака добавил бы метод вроде Neg или подобный.

Перегрузка операция предназначена для повышения читабельности программы. Не всегда и не все действия необходимо перегружать. Мне кажется, что вынос отдельного метода для смены знака было бы разумно.


Автор: Sartorius 20.1.2007, 14:53
прототип не тот... унарный минус без параметров
Код

class CMy {
public:
    CMy & operator-()
    {
       CMy res(*this);       
        res.m_value *= -1;
        return res;
    }
    int m_value;
};
void main()
{
    CMy myC;
    -myC;

}



Автор: SaDFromSpb 20.1.2007, 15:16
astilla, 
Если смена знака, о которой ты говоришь, это -m. (То есть просто поменять знак для одного класса). Значт тебе нужна форма operator-() без аргументов.

Код

class A {
public:
    A(int in) : i(in) {};
    
    A operator-(const A& other) {
        return A(i-other.i);
    };
    
    A operator-() {
        return A(-i);
    };
    
    void print() { cout<<"From A : "<<i<<endl; };
private:
   int i;
};



Цитата(astilla @  20.1.2007,  14:32 Найти цитируемый пост)
Mtrx &C = *(new Mtrx (m,n));
Так делать нехорошо. То, что выделилось по этой операции new, ты удалить уже не сможешь. Если нужно генерировать временный объект для далнейшего участия в операциях, следует использовать возвращение значения с размещением на стек.

Добавлено @ 15:19 
Добавлю, что когда я начал писать ответ, последним было сообщение Rockie  smile

Добавлено @ 15:27 
Цитата(Sartorius @  20.1.2007,  14:53 Найти цитируемый пост)
    CMy & operator-()
    {
       CMy res(*this);       
        res.m_value *= -1;
        return res;
    }

 Здесь так же проблема. Возвращается ссылка на автоматический объект, который тут же уничтожается. Результат - абракадабра.

Автор: astilla 20.1.2007, 15:28
ОГРОМНОЕ все спасибо!
Разобралась. Все получилось.
Спасибо за то, что вы все есть smile

Автор: Sartorius 20.1.2007, 15:43
Цитата

Здесь так же проблема. Возвращается ссылка на автоматический объект, который тут же уничтожается. Результат - абракадабра.

 Ты ошибаешься. Компилятор в этом случае создает копию res.

Автор: SaDFromSpb 20.1.2007, 15:52
Цитата(Sartorius @  20.1.2007,  15:43 Найти цитируемый пост)
Ты ошибаешься. Компилятор в этом случае создает копию res. 

Я тоже об этом подумал сначала. Проверл. Мой компилятор (cl из VisualStudio) работает, как я описываю. Да и по семантике он не должен копироваться, если мы ссылку возвращаем.

Автор: Axxent 20.1.2007, 15:57
Цитата

 Ты ошибаешься. Компилятор в этом случае создает копию res.

Если это и так, то скорее всего не везде, тем не менее в любом случае путать людей не стоит. Возвращать ссылку или указатель на объект созданный в стеке - не есть хорошо. 

Автор: Sartorius 20.1.2007, 16:11
SaDFromSpb, интересно. У мну VS2005 все работает корректно.

Автор: Axxent 20.1.2007, 16:21
Sartorius, 
даже если таким макаром возвращать объекты с динамическим выделением памяти, освобождающие память в деструкторе? Очень-очень не верится.

Автор: SaDFromSpb 21.1.2007, 16:26
Цитата(Sartorius @  20.1.2007,  16:11 Найти цитируемый пост)
SaDFromSpb, интересно. У мну VS2005 все работает корректно.

Убедись, что у твоего объекта вызывается копирующий конструктор именно при "возвращении" из метода (создай его реализацию с писалкой). (Он все-таки вряд ли вызвывается  smile ). Твой код работает нормально видимо только потому, что содержимое освобожденной в стэке памяти остается прежним до следующей операции выделения памяти в нем (Попробуй какие-нибудь стековые переменные позаводить с их инициализацией, а потом проверь работоспособность возвращенного таким макаром объекта).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)