Przeciążanie operatora dwuargumentowego w celu dodawania

0

Witam,
Uczę się C++, zbudowałem więc klasę do obsługi macierzy. Dodatkowo dziedzicząc utworzyłem klasę do obsługi macierzy kwadratowej i wyposażyłem ją np. w funkcje liczenia macierzy odwrotnych, wyznaczników.

Teraz zabrałem się za standardowe, podstawowe funkcje typu dodawanie/odejmowanie/mnożenie, ale w tym celu chcę użyć przeciążania operatorów i mam problem.

Stworzyłem funkcje globalną i zaprzyjaźniłem ją z klasą macierzystą.
Prototyp:

  matrix& operator+(const matrix&, const matrix&);

Funkcja:

  matrix& operator+(const matrix& a, const matrix& b)
  {
    matrix* c = new matrix(a.rows, a.columns);
    
    for(int i = 0; i < a.rows; ++i)
      for(int j = 0; j < a.columns; ++j)
	c->body[i][j] = a.body[i][j] + b.body[i][j]; 
      
    return *c;
  }

Działa tylko dla klasy matrix, czyli klasy ogólnej (operacja nie wykona się dla klasy dziedziczonej).

Pytania:

  1. Czy deklaracje przyjaźni są dziedziczone? Czy też muszę zaprzyjaźniać klasę utworzoną przez dziedziczenie na nowo? (to nie pomogło)
  2. Jak sprawić, by funkcja działała też dla klas wywodzących się z klasy macierzystej? Komunikat błędu w momencie dodawania klasy square_matrix za pomocą powyższej funkcji:
g++ -o main main.cpp matrix.cpp -g -pedantic
main.cpp: In function ‘int main()’:
main.cpp:36:11: error: no match for ‘operator=’ in ‘e = math::operator+((*(const math::matrix*)(& d.math::square_matrix::<anonymous>)), (*(const math::matrix*)(& d.math::square_matrix::<anonymous>)))’
main.cpp:36:11: note: candidate is:
matrix.h:25:9: note: math::square_matrix& math::square_matrix::operator=(const math::square_matrix&)
matrix.h:25:9: note:   no known conversion for argument 1 from ‘math::matrix’ to ‘const math::square_matrix&’
make: *** [all] Błąd 1

Zastanawia mnie sposób tworzenia obiektu. Jest on dla mnie dość dziwny. Tworzę wskaźnik (czyli obiekt zostaje utworzony na stercie?) czyli obiekt jest tworzony gdzieś w pamięci w trakcie działania programu. Na nowo utworzonym obiekcie operuje jak na zwykłym wskaźniku, co jest logiczne. Wykonuje porządaną operacje matematyczną. Następnie zwracam to, co znajduje się pod adresem nowo utworzonego obiektu. I tu pojawia się nie do końca zrozumienie różnicy między referencją i wskaźnikiem.
3. Czy jak funkcja ma zwrócić referencję po prostu należy zwrócić to, co jest pod adresem danego obiektu?
4. Jak to sprzątać? Klasa matrix ma swój destruktor, ale czy jest on w ogóle kiedykolwiek wywoływany?

Pozdrawiam,

4

user image

0
matrix& operator+(const matrix& a, const matrix& b)
  {
    matrix c(a.rows, a.columns);
 
    for(int i = 0; i < a.rows; ++i)
      for(int j = 0; j < a.columns; ++j)
        c.body[i][j] = a.body[i][j] + b.body[i][j]; 

    return c;
  }
0

Próbowałem tak na samym początku. Wywołuje to zakończenie programu błędem:
*** glibc detected *** ./main: double free or corruption (out): 0x000000000232f1b0 ***

Przed wykonaniem instrukcji return rzeczywiście, wewnątrz funkcji wartość sumy zgadza się. Ale destruktor powoduje zwolnienie zmiennej lokalnej, która została utworzona aby dodawać. Destruktor:

  matrix::~matrix() {
    for(int i = 0; i < rows; ++i)
      delete[] body[i];
    delete[] body;
  }

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