[C++] Klasa reprezentująca macierz

harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

Witam,
Mam problem z klasą macierz. Muszę przygotować na następne zajęcia funkcje operatorowe, ale nie mogę tego wykonać, gdyż nie mogę zdefiniować domyślnego konstruktora. Zanim się do tego zabrałem wszystko działało, ale problem się zaczyna, gdy deklaruje obiekt bez parametrów "C". Nawet jeśli pokombinuje i skompiluje mi program to problem zachodzi, gdy próbuje wykonać działanie "C=A+B". Z tego co zauważyłem problem występuje na tle alokacji danych. Czy ktoś pomoże mi to rozwiązać? Próbowałem się przekopać przez internet, ale nic ciekawego nie znalazłem.

Kod: Zaznacz cały

#include "Klasamacierz.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void Klasamacierz:: wypelnij_zerami()
{
	int i,j;
        for(i=0;i<wiersz;i++)
	{
		for(j=0;j<kolumna;j++)
		{
			macierz[i][j]=0;
		}
	}
}
void Klasamacierz:: wypelnij_jedynkami ()
{
	int i,j;
	for(i=0;i<wiersz;i++)
	{
		for(j=0;j<kolumna;j++)
		{
			macierz[i][j]=1;
		}
	}
}
void Klasamacierz:: wypelnij_losowo ()
{
	int i,j;
	for(i=0;i<wiersz;i++)
	{
		for(j=0;j<kolumna;j++)
		{
			macierz[i][j]=rand();
		}
	}
}
void Klasamacierz:: wyswietl ()
{
	    for(int i=0;i<wiersz;i++)
    {
        for(int j=0;j<kolumna;j++)
          {  cout<<macierz[i][j]<<"	";
  		}
		cout << endl;
	}
}

Klasamacierz Klasamacierz::
operator+(const Klasamacierz &b)
{
   Klasamacierz suma;
   if(wiersz==b.wiersz && kolumna==b.kolumna)
   {
	for(int i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			suma.macierz[i][j]=b.macierz[i][j]+macierz[i][j];
		}
	}
}
   else
   {
	   cout << "Dodawanie niemozliwe" << endl;
}

    
    return suma;
}



Klasamacierz::Klasamacierz(void)
{
	int **macierz=NULL;
}
Klasamacierz::Klasamacierz(int _wiersz, int _kolumna):wiersz(_wiersz),kolumna(_kolumna){
	macierz=new int*[wiersz];
	for(int i=0;i<wiersz;i++)
	{
		macierz[i]=new int[kolumna];
		for(int j=0;j<kolumna;j++)
		{
			macierz[i][j]=0;
		}
	}

}
Klasamacierz::Klasamacierz(const Klasamacierz &X):wiersz(X.wiersz),kolumna(X.kolumna)
{
		macierz=new int*[wiersz];
	for(int i=0;i<wiersz;i++)
	{
		macierz[i]=new int[kolumna];
		for(int j=0; j<kolumna;j++)
		{
			macierz[i][j]=X.macierz[i][j];
		}
	}
}
Klasamacierz::~Klasamacierz(void)
{
	   for(int i=0;i<wiersz;i++)
        delete []macierz[i];
    delete []macierz;
}
Plik main:

Kod: Zaznacz cały

#include<iostream>
#include <cstdlib>
#include <ctime>
#include "Klasamacierz.h"
using namespace std;


int main()
{
	srand( time( NULL ) );
	int m,n;
	cout << "Podaj liczbe wierszy: " << endl;
	cin >> m;
	cout << "Podaj liczbe kolumn: " << endl;
	cin >> n;
	
    Klasamacierz A(m,n);

	A.wypelnij_losowo ();
	A.wyswietl ();
	
	cout << "Podaj liczbe wierszy: " << endl;
	cin >> m;
	cout << "Podaj liczbe kolumn: " << endl;
	cin >> n;
	Klasamacierz B(m,n);
	B.wypelnij_losowo();
	B.wyswietl();
Klasamacierz C;
		system("pause");
return 0;
}
Mogę wkleić również plik nagłowkowy jeśli będzie taka konieczność.
Ostatnio zmieniony 1 maja 2015, o 20:38 przez Afish, łącznie zmieniany 3 razy.
Powód: Poprawa wiadomości.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Klasa reprezentująca macierz

Post autor: Afish »

Kod: Zaznacz cały

Klasamacierz::Klasamacierz(void)
{
   int **macierz=NULL;
}
Średnio przydatna będzie tak utworzona macierz. W szczególności używanie jej w operatorze dodawania zapewne skończy się niepoprawnym dostępem do pamięci.
harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

No dobrze, ale jak mam napisać taki konstruktor, który stworzy macierz bez parametrów, która będę mógł uzyć w operacji dodawania? Wiadomo, że w czasię funkcji operatorowej taka macierz będzie musiała mieć liczbe wierszy i kolumn równą poprzednim, ale nie wiem jak tego dokonać.

Kod: Zaznacz cały


Klasamacierz::Klasamacierz(void)
{
   
wiersz=0;
kolumna=0;
}macierz=new int*[wiersz];
	for(int i=0;i<wiersz;i++)
	{
		macierz[i]=new int[kolumna];
		for(int j=0; j<kolumna;j++)
		{
			macierz[i][j]=0;
		}
	}
Taka deklaracja macierzy bezparametru działa, ale wtedy i tak funkcja operatorowa z dodawaniem nie działa, więc nie wiem jak przejść przez to. To logicznie, że skoro tak zadeklaruje taką macierz, to nie będę jej użyć w funkcji operatorowej, ale nic innego mi nie przychodzi do głowy. Pomocy!
Ostatnio zmieniony 17 kwie 2015, o 21:09 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Klasa reprezentująca macierz

Post autor: Afish »

Ale po co Ci konstruktor bez parametrów? W operatorze dodawania przecież wiesz, jakie wymiary powinna mieć wynikowa macierz. Śmiem nawet twierdzić, że tworzenie macierzy bez podania wymiarów nie będzie miało sensu w żadnym miejscu.
A jeżeli już chcesz mieć konstruktor bez parametrów, to musisz zadbać o to, aby w odpowiednim miejscu zaalokować pamięć. A że nie wiesz przy tworzeniu, jak duża macierz ma to być, to musisz tę decyzję podjąć później, na przykład przez wywołanie kolejnej metody klasy. Ale to rozwiązanie na siłę.
harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

W każdym razie zanim wywołam funkcje operatorową, muszę wcześniej zadeklarować wynikową macierz(Klasamacierz C), bo przeciwnym razie program mi tego nie skompliuje. SKoro uważasz ten konstruktor jest mi do niczego potrzebny, to czy mógłbyś mi pokazać w jaki sposób mogę wywołać tą funkcję? Z góry dzięki.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Klasa reprezentująca macierz

Post autor: Afish »

Kod: Zaznacz cały

Klasamacierz Klasamacierz::
operator+(const Klasamacierz &b)
{
   Klasamacierz suma;
   if(wiersz==b.wiersz && kolumna==b.kolumna)
   {
   for(int i=0;i<wiersz;i++)
   {
      for(int j=0;j<kolumna;j++)
      {
         suma.macierz[i][j]=b.macierz[i][j]+macierz[i][j];
      }
   }
}
   else
   {
      cout << "Dodawanie niemozliwe" << endl;
}

    
    return suma;
}
Jakie wymiary ma tutaj macierz suma? A jakie mieć powinna?
Jak tworzysz macierz suma? A jak ją utworzyć, żeby mieć pożądane wymiary?
Jak rozwiążesz ten problem, to utworzenie macierzy C w metodzie main sprowadzi się do wywołania operatora dodawania.
harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

Kod: Zaznacz cały

Klasamacierz suma(this->wiersz, this->kolumna);
O to chodziło? Jeśli tak to dzięki, bo działa! Jednakże, mogę jedynie wywołać ten operator poprzez:

Kod: Zaznacz cały

Klasamacierz C=A+B;
W związku z tym co bym musiał zrobić, abym mógł wywołać go w taki sposób:

Kod: Zaznacz cały

Klasamacierz C
C=A+B;
Nie daję mi to spokoju.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Klasa reprezentująca macierz

Post autor: Afish »

harleyzg pisze:

Kod: Zaznacz cały

Klasamacierz suma(this->wiersz, this->kolumna);
O to chodziło? Jeśli tak to dzięki, bo działa! :D
Tak, o to.
harleyzg pisze:W związku z tym co bym musiał zrobić, abym mógł wywołać go w taki sposób:

Kod: Zaznacz cały

Klasamacierz C
C=A+B;
Nie daję mi to spokoju.
Akurat ten kod skompilowałby się przy użyciu pierwszej wersji Twojego programu, tylko wywaliłby się w momencie dodawania, bo tam źle tworzyłeś macierz wynikową. Teraz powinien zadziałać poprawnie (przy założeniu, że nie usunąłeś konstruktora bezparametrowego).
Jednocześnie zauważ, że te dwie linijki utworzą dwa obiekty macierzy, z których jeden przestanie być dostępny (dlaczego?).
harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

Sprawdziłem jeszcze raz program z tym konstruktorem domyślnym i ta linijka kodu nie kompiluje. Bez konstruktora bezparametrowego też.

Kod: Zaznacz cały

Klasamacierz C
C=A+B;
Afish pisze:Jednocześnie zauważ, że te dwie linijki utworzą dwa obiekty macierzy, z których jeden przestanie być dostępny (dlaczego?).
Jedyne co mi przychodzi do głowy to, że obiekt C zostanie utworzony w konstruktorze. Niekoniecznie utworzony o parametrach wymagających przez funkcja operatorowa, więc nie może być potem używany. W wyniku tego, że jakaś pamięć już została zalokowana, to w tym obiekcie nie można tego powiększyć. Dobrze kombinuje? ;D
Błąd wyskakuje taki:

Kod: Zaznacz cały

Unhandled exception at 0x011217c2 in macierz.deluxe.exe: 0xC0000005: Access violation reading location 0xfeeefeee.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Klasa reprezentująca macierz

Post autor: Afish »

harleyzg pisze:Sprawdziłem jeszcze raz program z tym konstruktorem domyślnym i ta linijka kodu nie kompiluje. Bez konstruktora bezparametrowego też.

Kod: Zaznacz cały

Klasamacierz C
C=A+B;
Bo nie masz średnika w pierwszej linijce. Osobną kwestią jest fakt, że gdy to już się skompiluje, to zapewne nie będzie działało z powodu niepoprawnych odwołań do pamięci.
harleyzg pisze:Jedyne co mi przychodzi do głowy to, że obiekt C zostanie utworzony w konstruktorze. Niekoniecznie utworzony o parametrach wymagających przez funkcja operatorowa, więc nie może być potem używany. W wyniku tego, że jakaś pamięć już została zalokowana, to w tym obiekcie nie można tego powiększyć. Dobrze kombinuje? ;D
Nie. W pierwszej linijce utworzysz obiekt, ale w drugiej linijce do tej samej zmiennej przypiszesz inny obiekt. Popatrz na alokację pamięci i sprawdź, czy gdzieś nie ma wycieku.
harleyzg pisze: Błąd wyskakuje taki:

Kod: Zaznacz cały

Unhandled exception at 0x011217c2 in macierz.deluxe.exe: 0xC0000005: Access violation reading location 0xfeeefeee.
Niezainicjalizowany wskaźnik i złe odwołanie do pamięci.
harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

Afish pisze:
harleyzg pisze:Jedyne co mi przychodzi do głowy to, że obiekt C zostanie utworzony w konstruktorze. Niekoniecznie utworzony o parametrach wymagających przez funkcja operatorowa, więc nie może być potem używany. W wyniku tego, że jakaś pamięć już została zalokowana, to w tym obiekcie nie można tego powiększyć. Dobrze kombinuje? ;D
Nie. W pierwszej linijce utworzysz obiekt, ale w drugiej linijce do tej samej zmiennej przypiszesz inny obiekt. Popatrz na alokację pamięci i sprawdź, czy gdzieś nie ma wycieku.
Dalej nie mogę znaleźć rozwiązania.
Po wyskoczeniu błędu, o którym wspomniałem wcześniej. Kompilator odsyła mnie do tego fragmentu kodu:

Kod: Zaznacz cały

void Klasamacierz:: wyswietl ()
{
	    for(int i=0;i<wiersz;i++)
    {
        for(int j=0;j<kolumna;j++)
          {  cout<<macierz[i][j]<<"	";
  		}
		cout << endl;
	}
}
Strzałka pokazuje na to miejsce:

Kod: Zaznacz cały

          {  cout<<macierz[i][j]<<"	";
Mógłbyś mi pokazać, co należałoby konkretnie zmienić? Ewentualnie napisać jak rozwiązanie powinno wyglądać? Patrzę na ten kod i naprawdę nic mi nie przychodzi do głowy.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Klasa reprezentująca macierz

Post autor: Afish »

Wklej cały kod i log z kompilacji, szklane kule niestety wyszły z mody.
harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

Kod: Zaznacz cały

#include "Klasamacierz.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void Klasamacierz:: wypelnij_zerami()
{
	for(int	i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			macierz[i][j]=0;
		}
	}
}
void Klasamacierz:: wypelnij_jedynkami ()
{
	for(int i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			macierz[i][j]=1;
		}
	}
}
void Klasamacierz:: wypelnij_losowo ()
{
	for(int i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			macierz[i][j]=rand();
		}
	}
}
void Klasamacierz:: wyswietl ()
{
	    for(int i=0;i<wiersz;i++)
    {
        for(int j=0;j<kolumna;j++)
          {  cout<<macierz[i][j]<<"\t";
  		}
		cout << endl;
	}
}

Klasamacierz Klasamacierz::
operator+(const Klasamacierz &b)
{
	Klasamacierz suma(this->wiersz, this->kolumna);
   if(wiersz!=b.wiersz || kolumna!=b.kolumna)
   {
	   cout << "Dodawanie niemozliwe" << endl;
   }
   else
   { 
	for(int i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			suma.macierz[i][j]=macierz[i][j]+b.macierz[i][j];
		}
	}
   }
    return suma;
}
Klasamacierz Klasamacierz::
operator+=(const Klasamacierz &b)
{
	   if(wiersz!=b.wiersz || kolumna!=b.kolumna)
   {
	   cout << "Dodawanie niemozliwe" << endl;
   }
   else
   { 
	for(int i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			macierz[i][j]=macierz[i][j]+b.macierz[i][j];
		}
	}
   }
    return *this;
}
Klasamacierz Klasamacierz::operator-(const Klasamacierz &b)
{
	Klasamacierz roznica(this->wiersz, this->kolumna);
   if(wiersz!=b.wiersz || kolumna!=b.kolumna)
   {
	   cout << "Odejmowanie niemozliwe" << endl;
   }
   else
   {    
	for(int i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			roznica.macierz[i][j]=macierz[i][j]-b.macierz[i][j];
		}
	}
   }
    return roznica;
}
Klasamacierz Klasamacierz::
operator-=(const Klasamacierz &b)
{
	   if(wiersz!=b.wiersz || kolumna!=b.kolumna)
   {
	   cout << "Odejmowanie niemozliwe" << endl;
   }
   else
   { 
	for(int i=0;i<wiersz;i++)
	{
		for(int j=0;j<kolumna;j++)
		{
			macierz[i][j]=macierz[i][j]-b.macierz[i][j];
		}
	}
   }
    return *this;

}
Klasamacierz Klasamacierz::operator*(const Klasamacierz &b)
{
	int suma=0,tmp;
	Klasamacierz iloczyn(this->wiersz, b.kolumna);
	if(this->kolumna==b.wiersz)
	{
		for(int i=0;i<this->wiersz;i++)
		{
			for(int j=0;j<b.kolumna;j++)
			{
				for(int z=0;z<this->kolumna;z++)
				{
					tmp=macierz[i][z]*b.macierz[z][j];
					suma=suma+tmp;
					tmp=0;
				}
				iloczyn.macierz[i][j]=suma;
				suma=0;
			}
		}	
	}
	return iloczyn;
}

Klasamacierz::Klasamacierz(void)
{
	
wiersz=0;
kolumna=0;
macierz=new int*[wiersz];
   for(int i=0;i<wiersz;i++)
   {
      macierz[i]=new int[kolumna];
      for(int j=0; j<kolumna;j++)
      {
         macierz[i][j]=0;
      }
   }
}
Klasamacierz::Klasamacierz(int _wiersz, int _kolumna):wiersz(_wiersz),kolumna(_kolumna){
	macierz=new int*[wiersz];
	for(int i=0;i<wiersz;i++)
	{
		macierz[i]=new int[kolumna];

	}
}
Klasamacierz::Klasamacierz(const Klasamacierz &X):wiersz(X.wiersz),kolumna(X.kolumna)
{
		macierz=new int*[wiersz];
	for(int i=0;i<wiersz;i++)
	{
		macierz[i]=new int[kolumna];
		for(int j=0; j<kolumna;j++)
		{
			macierz[i][j]=X.macierz[i][j];
		}
	}
}
Klasamacierz::~Klasamacierz(void)
{
	   for(int i=0;i<wiersz;i++)
        delete []macierz[i];
    delete []macierz;
}
Plik main:

Kod: Zaznacz cały

#include<iostream>
#include <cstdlib>
#include <ctime>
#include "Klasamacierz.h"
using namespace std;
int main()
{
	srand( time( NULL ) );
	int m,n;
	cout << "Podaj liczbe wierszy: " << endl;
	cin >> m;
	cout << "Podaj liczbe kolumn: " << endl;
	cin >> n;
    Klasamacierz A(m,n);
	A.wypelnij_losowo ();
	A.wyswietl ();
	cout << "Podaj liczbe wierszy: " << endl;
	cin >> m;
	cout << "Podaj liczbe kolumn: " << endl;
	cin >> n;
	Klasamacierz B(m,n);
	B.wypelnij_losowo();
	B.wyswietl();

	Klasamacierz C;
	C=A+B;
        C.wyswietl();
	
	system("pause");
	return 0;
}
Plik nagłowkowy:

Kod: Zaznacz cały

#pragma once
class Klasamacierz
{
	int wiersz;
	int kolumna;
	int **macierz;
public:
	

	void wypelnij_zerami();
	void wypelnij_jedynkami();
	void wyswietl();
	void wypelnij_losowo();
	Klasamacierz operator+(const Klasamacierz &b);
	Klasamacierz operator-(const Klasamacierz &b);
	Klasamacierz operator*(const Klasamacierz &b);
	Klasamacierz operator+=(const Klasamacierz &b);
	Klasamacierz operator-=(const Klasamacierz &b);
	Klasamacierz operator*=(const Klasamacierz &b);
	Klasamacierz(void);
	Klasamacierz(int _wiersz, int _kolumna);
	Klasamacierz(const Klasamacierz &X);


	~Klasamacierz(void);
};
Log:

Kod: Zaznacz cały

'macierz.deluxe.exe': Loaded 'C:\Users\Filip\Documents\Visual Studio 2010\Projects\macierz.deluxe\Debug\macierz.deluxe.exe', Symbols loaded.
'macierz.deluxe.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', Cannot find or open the PDB file
'macierz.deluxe.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', Cannot find or open the PDB file
'macierz.deluxe.exe': Loaded 'C:\Windows\SysWOW64\KernelBase.dll', Cannot find or open the PDB file
'macierz.deluxe.exe': Loaded 'C:\Program Files\Bitdefender\Antivirus Free Edition\avc3\avc3_sig_298\avcuf32.dll', Cannot find or open the PDB file
'macierz.deluxe.exe': Loaded 'C:\Windows\SysWOW64\msvcp100d.dll', Symbols loaded.
'macierz.deluxe.exe': Loaded 'C:\Windows\SysWOW64\msvcr100d.dll', Symbols loaded.
First-chance exception at 0x011d17c2 in macierz.deluxe.exe: 0xC0000005: Access violation reading location 0xfeeefeee.
Unhandled exception at 0x011d17c2 in macierz.deluxe.exe: 0xC0000005: Access violation reading location 0xfeeefeee.
Awatar użytkownika
Dasio11
Moderator
Moderator
Posty: 10225
Rejestracja: 21 kwie 2009, o 19:04
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 40 razy
Pomógł: 2362 razy

[C++] Klasa reprezentująca macierz

Post autor: Dasio11 »

Problem jest spowodowany przez kawałek:

Kod: Zaznacz cały

Klasamacierz C;
C=A+B;
C.wyswietl();
Przeanalizujmy linijka po linijce, co ten kod naprawdę robi.

1. Klasamacierz C;

Wywołuje konstruktor bezparametrowy klasy Klasamacierz dla obiektu C, czyli alokuje tablicę dwuwymiarową 0x0.

2. C=A+B;

Tutaj dzieje się trochę więcej. Najpierw ciało operatora dodawania konstruuje lokalny obiekt suma przy użyciu konstruktora pobierającego rozmiary macierzy i wpisuje do niego takie wartości, jakie powinna mieć suma macierzy A + B.
Potem działa domyślny operator przypisania, który kopiuje wszystkie pola obiektu suma do obiektu C - zatem macierz C będzie mieć nie tylko takie same wartości pól wiersz i kolumna, ale również wskaźnik macierz będzie wskazywał na to samo miejsce w pamięci.
Na końcu na obiekcie lokalnym suma wywoływany jest destruktor, który dealokuje całą jego pamięć. A ponieważ C wskazuje na dokładnie tę samą pamięć, więc teraz zawiera on niepoprawny wskaźnik.
Ponadto, zaalokowany wcześniej wskaźnik na tablicę 0x0 zostaje zapomniany, co prowadzi do wycieku pamięci.

3. C.wyswietl();

Wywołanie do pamięci wskazywaną przez C.macierz powoduje błąd z opisanych wyżej przyczyn.


Jak to naprawić? Należy zaimplementować własny operator przypisania operator= - w taki sposób, żeby wywołanie A = B wywoływało destruktor A, alokowało nową pamięć dla A i kopiowało wartości z macierzy B.
Krótko: domyślny operator przypisania kopiuje ze źródła do celu wskaźnik macierz, a poprawny operator przypisania powinien kopiować wartości wskazywane przez ten wskaźnik.
harleyzg
Użytkownik
Użytkownik
Posty: 47
Rejestracja: 1 lis 2014, o 22:38
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 8 razy

[C++] Klasa reprezentująca macierz

Post autor: harleyzg »

Dzięki! Wszystko działa!

Kod: Zaznacz cały

Klasamacierz & Klasamacierz::operator=(const Klasamacierz &b)

{
	   for(int i=0;i<wiersz;i++)
        delete []macierz[i];
    delete []macierz;
	wiersz=b.wiersz;
	kolumna=b.kolumna;
		macierz=new int*[wiersz];
	for(int i=0;i<wiersz;i++)
	{
		macierz[i]=new int[kolumna];
		for(int j=0; j<kolumna;j++)
		{
			macierz[i][j]=b.macierz[i][j];
		}

	}

	return *this;
}
Dla upewnienie spytam tylko, czy o to dokładnie chodziło?
ODPOWIEDZ