Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Visual C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.04.2012, 10:44   #1
SmileOn
Новичок
Джуниор
 
Регистрация: 28.04.2012
Сообщений: 4
По умолчанию Перегрузка операторов

В общем проблема такая:
Помогаю знакомому с лабами по с++, гемор возник внезапно на перегрузке операторов.
Есть класс, реализующий квадратную матрицу - SqMatrix

в мэйне выражение
s = m + m; //объекты sqmatrix
Сначала вызывается сложение, где создается создается объект "r", куда вычисляется результат сложения. Если перед выходом из функции напечатать "r" все прекрасно, результат правильный.
Однако почемуто перед самым выходом из функции (перед return r) почему то вызывается деструктор для r.

После этого вызывается оператор присваивания, и в него передается как параметр временный объект rigth_side. Еще до входа в тело функции (стрелочка дебагера на фигурной скобке) объект rigth_side правильный, поля объекта заполнены правильными цифрами. Однако после того как делается шаг - теперь уже в теле функции, в параметре (rigth_side) лежит мусор!

Я уже всю голову сломал, в перегрузке операторов не особо разбираюсь, поэтому возможно чтото упустил...

main()
Код:
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

#include "SqMatrix.h"
void main()
{
	system("cls");
	int msize;
	printf("Type matrix size (size > 0) && (size < 40)> ");
	scanf("%i", &msize);
	if((msize < 1) || (msize > 40))
	{
		printf("\nsize is out of range, using default value, size = 5");
		msize = 5;
	}
	SqMatrix m(msize), s(0);
	m.zap();
	s = m + m;
	m.print();
	s.print();
	_getch();
}

SqMatrix.h
Код:
#pragma once
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
class SqMatrix
{

public:
	SqMatrix(int size);					//конструктор, в качестве параметра принимает размер (по умолчанию = 0)
	SqMatrix(SqMatrix & othermatrix);	//конструктор копирования
	~SqMatrix(void);					//деструктор
	void flip90(int flipnum);				//поворот матрицы
	void print();						//вывод на экран
	void zap();							//заполнение
	void resize(int size);
	SqMatrix& operator =(const SqMatrix &othermatrix);
friend SqMatrix& operator + (SqMatrix &a1, SqMatrix &a2);
private:
	int **ptr;
	int size;
	void memfree();
	void memalloc(int size);
};
SqMatrix.cpp
Код:
#include "SqMatrix.h"
SqMatrix::SqMatrix(int size = 0)
{
	this->size = size;								//установка размера
	memalloc(size);
	zap();
}

SqMatrix::SqMatrix(SqMatrix &othermatrix)			//конструктор копирования
{

	memfree();										
	size = othermatrix.size;
	memalloc(size);

	for(int i = 0; i < size; i ++)					
		for(int j = 0; j < size; j ++)
			ptr[i][j] = othermatrix.ptr[i][j];
}
SqMatrix::~SqMatrix(void)							
{
	memfree();
}

SqMatrix &SqMatrix::operator=(const SqMatrix &right_side)
{
	memfree();	
	size = right_side.size;
	memalloc(size);

	for(int i = 0; i < size; i ++)
		for(int j = 0; j < size; j ++)
			ptr[i][j] = right_side.ptr[i][j];

	return *this;
}

void SqMatrix::print()
{
	for(int i = 0; i < size; i++)
	{
		for(int j = 0; j < size; j++)
			printf("%i\t", ptr[i][j]);

		printf("\n");
	}
}
void SqMatrix::zap()//заполнение матрицы значениями из первого задания
{
	for(int i = 0; i < size; i++)//заполнение недиагональных элементов (значение равно сумме индексов + 2)
		for(int j = 0; j < size; j++)
			if(i != j)
				ptr[i][j] = i + j + 2;

	for(int k = 0; k < size; k ++)				//заполнение диагональных элементов (индексы равны)
	{
		int sum = 0;
		for(int i = 0; i < size; i++)				//подсчет суммы элементов в тойже строке
			if(i != k) sum += ptr[i][k];

		for(int j = 0; j < size; j++)				//подсчет суммы элементов в том же столбце
			if(j != k) sum += ptr[k][j];

		ptr[k][k] = sum;
	}
}

void SqMatrix::flip90(int flipnum = 1)				
{													
	for(int flp = 0; flp < flipnum%4; flp ++)
	{
		int temp;
		for (int i = 0; i < (size + 1) / 2; i ++)
		{
			for (int j = 0; j < size / 2; j ++)
			{
				temp = ptr[j] [i];
				ptr[j] [i] = ptr[size - 1 - i][j];
				ptr[size - 1 - i] [j] = ptr[size - 1 - j] [size - 1 - i];
				ptr[size - 1 - j] [size - 1 - i] = ptr[i] [size - 1 - j];
				ptr[i] [size - 1 - j] = temp;
			}
		}
	}
}

void SqMatrix::resize(int size)
{
	if(size < 0) return;
	memfree();
	this->size = size;
	ptr = new int* [size];
	for(int i = 0; i < size; i ++)
		ptr[i] = new int;
	zap();
}


void SqMatrix::memfree()
{
	for(int i = 0; i < size; i ++)
		delete [] ptr[i];
	delete [] ptr;
}

void SqMatrix::memalloc(int size)
{
	if(size == 0)
	{
		ptr = NULL;
		return;
	}
	ptr = new int* [size];
	for(int i = 0; i < size; i ++)
		ptr[i] = new int[size];
}

SqMatrix& operator + (SqMatrix &a1, SqMatrix &a2)
{
	if(a1.size != a2.size)
	{
		printf("\nAddition impossible, size not equal!");
		return SqMatrix(0);
	}

	SqMatrix r(a1.size);
	for(int i = 0; i < a1.size; i++)
		for(int j = 0; j < a1.size; j++)
			r.ptr[i][j] = a1.ptr[i][j] + a2.ptr[i][j];
	r.print();
	return r;
}

Последний раз редактировалось SmileOn; 28.04.2012 в 10:51.
SmileOn вне форума Ответить с цитированием
Старый 28.04.2012, 11:10   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Вы отлично разбираетесь. Осталось понять, что ...

Цитата:
SqMatrix & operator +(....)
{
SqMatrix r(a1.size); // это локальный объект видимый только в блоке оператора.
//...
return r; // при выходе из функции он уничтожается
}
Надо бы сделать, чтобы при возврате из функции он передал свою копию.
Убрать амперсанд из возвращаемого значения SqMatrix& operator +(....)
Тем более, что конструктор копирования у Вас предусмотрен.

Последний раз редактировалось EUGY; 28.04.2012 в 11:12.
EUGY вне форума Ответить с цитированием
Старый 28.04.2012, 11:23   #3
SmileOn
Новичок
Джуниор
 
Регистрация: 28.04.2012
Сообщений: 4
По умолчанию

Спасибо. Теперь разобрался. Правда, когда создается копия, для возврата, сразу вызывается конструктор копирования, в котором первым делом освобождается память от старых данных, а тут этих данных понятное дело нет, там мусор, ну и фатал еррор как следствие. Ну это уже вопросы реализации. Это можно было бы решить флагами (если хоть один стандартный конструктор вызывался, то выставляем флаг и в конструкторе копирования память очищаем, если же конструктор копирования - это первый конструктор, который вызвался для этого объекта, то память не очищаем. Но если ни одного конструктора не вызывалось то как инициализировать флаг? Может быть есть другой, более правильный механизм?

Последний раз редактировалось SmileOn; 28.04.2012 в 11:32.
SmileOn вне форума Ответить с цитированием
Старый 28.04.2012, 11:32   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Члены ptr и size во всех типах конструкторов проинициализируйте нулем.
Чтобы при вызове memfree не напороться на ошибку.
Впрочем, я вот с первого раза и не вижу, зачем ее вообще вызывать в конструкторах.
EUGY вне форума Ответить с цитированием
Старый 28.04.2012, 11:35   #5
SmileOn
Новичок
Джуниор
 
Регистрация: 28.04.2012
Сообщений: 4
По умолчанию

Сейчас попробую определить конструктор по умолчанию, возможно это поможет, если он вызовется до конструктора копирования
SmileOn вне форума Ответить с цитированием
Старый 28.04.2012, 11:40   #6
SmileOn
Новичок
Джуниор
 
Регистрация: 28.04.2012
Сообщений: 4
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Члены ptr и size во всех типах конструкторов проинициализируйте нулем.
Чтобы при вызове memfree не напороться на ошибку.
Впрочем, я вот с первого раза и не вижу, зачем ее вообще вызывать в конструкторах.
Да, действительно, все верно.
Теперь я понял наконец, почему присваивание не определяют как friend, а определяют как член класса
SmileOn вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
перегрузка операторов C++ Kingdom_Reborn Помощь студентам 0 29.09.2011 20:58
Перегрузка операторов _-Re@l-_ Паскаль, Turbo Pascal, PascalABC.NET 11 20.11.2010 13:23
перегрузка операторов mashuta_ya Общие вопросы C/C++ 0 01.10.2010 18:54
Перегрузка операторов. Macb3th Общие вопросы C/C++ 5 01.04.2010 21:14
Перегрузка операторов, Организация перегрузки операторов chagin_yav Помощь студентам 2 12.05.2008 09:15