Problem ze zwracaniem obiektu

0

Witam, piszę z następującym problemem. Piszę program obsługujący działania na macierzach. Natrafiłem na pewien problem, a dokładnie najprawdopodobniej na problem związany ze zwracaniem obiektu. Poniżej wklejam przeciążone operatory + i *:

	Macierz& operator=(const Macierz& M)
	{
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 2; j++)
				tab[i][j] = M.tab[i][j];
		}
		return *this;
	}
	
	Macierz& operator *(const Macierz& m)
	{

		Macierz M;
		M.tab[0][0] = (m.tab[0][0] * tab[0][0]) + (m.tab[0][1] * tab[1][0]);
		M.tab[0][1] = (m.tab[0][0] * tab[0][1]) + (m.tab[0][1] * tab[1][1]);
		M.tab[1][0] = (m.tab[1][0] * tab[0][0])+ (m.tab[1][1] * tab[1][0]);
		M.tab[1][1] = (m.tab[1][0] * tab[0][1])+ (m.tab[1][1] * tab[1][1]);
		return  M;
	}

Problem pojawia się gdy w main chcę wykonać operacje np:

int main()
{
	// ... wcześniejsza deklaracja wartości w macierzach 
        // C A B - macierze 

	C = (A * B);

        // ...  reszta kodu
	return 0;
}

W tym momencie powstaje błąd i program przestaje działać. Zauważyłem, że problem polega na zwracaniu obiektu przez operator*. Gdy lekko zmienię kod do postaci :

	Macierz& operator *(const Macierz& m)
	{
		tab[0][0] = (m.tab[0][0] * tab[0][0]) + (m.tab[0][1] * tab[1][0]);
		tab[0][1] = (m.tab[0][0] * tab[0][1]) + (m.tab[0][1] * tab[1][1]);
		tab[1][0] = (m.tab[1][0] * tab[0][0])+ (m.tab[1][1] * tab[1][0]);
		tab[1][1] = (m.tab[1][0] * tab[0][1])+ (m.tab[1][1] * tab[1][1]);
		return  *this;
	}

(znam definicje this, wiem jak on działa)
wszystko zaczyna działać poprawnie lecz zmianie ulegają również wartość macierzy A. Czy mógłby ktoś pomóc, wesprzeć dobrą radą jak rozwiązać ten problem ?? ( podkreślam ja się jeszcze uczę :D) Dzięki wszystkim za pomoc :D

2
Macierz& operator *(const Macierz& m)
    {

        Macierz M;
        // [...]
        return  M;
    }

Problem jest w tym, że zwracasz referencję (de facto wskaźnik) na zmienną, której czas życia kończy się wraz z końcem funkcji. Co zrobić żeby tego uniknąć? Najprościej jest chyba podać inny typ zwracany, tzn Macierz zamiast Macierz&, co by było zgodne z konwencją.

0
enedil napisał(a):
> Macierz& operator *(const Macierz& m)
>     {
> 
>         Macierz M;
>         // [...]
>         return  M;
>     }
> ```
> Problem jest w tym, że zwracasz referencję (de facto wskaźnik) na zmienną, której czas życia kończy się wraz z końcem funkcji. Co zrobić żeby tego uniknąć? Najprościej jest chyba podać inny typ zwracany, tzn `Macierz` zamiast `Macierz&`, co by było zgodne z konwencją.

dzięki za odpowiedź, niestety próbowałem już tego wcześniej i nic to nie zmienia :/
1

Pokaż więcej kodu, bo to zdecydowanie jest błąd. Polecam też lekturę: https://dsp.krzaq.cc/post/304/jak-przeladowywac-operatory-w-mojej-klasie/

0
kq napisał(a):

Pokaż więcej kodu, bo to zdecydowanie jest błąd. Polecam też lekturę: https://dsp.krzaq.cc/post/304/jak-przeladowywac-operatory-w-mojej-klasie/

Klasa:

class Macierz
{
private:
	float** tab;
public:
    // Konstruktor
	Macierz() { tab = new float* [2]; Table();};
	// Destruktor
	~Macierz()
	{
		for (int i = 0; i < 2; i++)
			delete[] tab[i];

		delete[] tab;
	};
	// Metody publiczne
	void Set(int A, int B, float C);
        void Get();
        private:
	void Table();
	// Przeciazenie operatorow
	Macierz& operator=(const Macierz &M)
	{
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 2; j++)
				tab[i][j] = M.tab[i][j];
		}
		return *this;
	}
	
	Macierz& operator *(const Macierz& m)
	{


		Macierz M;

		M.tab[0][0] = (m.tab[0][0] * tab[0][0]) + (m.tab[0][1] * tab[1][0]);
		M.tab[0][1] = (m.tab[0][0] * tab[0][1]) + (m.tab[0][1] * tab[1][1]);
		M.tab[1][0] = (m.tab[1][0] * tab[0][0])+ (m.tab[1][1] * tab[1][0]);
		M.tab[1][1] = (m.tab[1][0] * tab[0][1])+ (m.tab[1][1] * tab[1][1]);
		return  M;
	}
};

Metody:

void Macierz::Set(int A, int B, float C)
{
    tab[A][B] = C;
}

void Macierz::Table()
{
    for (int i = 0; i < 2; i++)
        tab[i] = new float[2];
}

void Macierz::Get()
{
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
            std::cout << tab[i][j]<<" ";

        std::cout << "\n";
    }
}

main:

int main()
{
	Macierz A,B,C; 

	A.Set(0, 0, 1.0);
	A.Set(0, 1, 2.0);
	A.Set(1, 0, 3.0);
	A.Set(1, 1, 4.0);

	B = A;

	B.Set(0, 0, 5.0);

	A.Get();
	std::cout << "\n";
	B.Get();
	std::cout << "\n";

	C = A * B; // Tutaj powstaje problem 

	C.Get();
	std::cout << "\n";

	return 0;
}
1

Ten kod się nie kompiluje:

macierze.cpp: In function ‘int main()’:
macierze.cpp:77:9: error: ‘Macierz& Macierz::operator=(const Macierz&)’ is private within this context
   77 |     B = A;
      |         ^
macierze.cpp:23:14: note: declared private here
   23 |     Macierz& operator=(const Macierz &M)
      |              ^~~~~~~~
macierze.cpp:86:13: error: ‘Macierz& Macierz::operator*(const Macierz&)’ is private within this context
   86 |     C = A * B; // Tutaj powstaje problem
      |             ^
macierze.cpp:33:14: note: declared private here
   33 |     Macierz& operator *(const Macierz& m)
      |              ^~~~~~~~
macierze.cpp:86:13: error: ‘Macierz& Macierz::operator=(const Macierz&)’ is private within this context
   86 |     C = A * B; // Tutaj powstaje problem
      |             ^
macierze.cpp:23:14: note: declared private here
   23 |     Macierz& operator=(const Macierz &M)
      |              ^~~~~~~~
make: *** [<wbudowane>: macierze] Błąd 1

Podaj faktyczny kod, a nie jakieś ad hoc modyfikacje

0

Operatory masz w zakresie prywatnym : usuń słowo :private które przez pomyłkę jest tam wstawione.
Pomyśl nad zrobieniem własnego konstruktora kopiującego, gdyż teraz masz zaimplementowaną shallow copy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1