Przeciążanie operatora dwuargumentowego w celu dodawania

Newb
2011-09-24 21:05
Newb
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,

Pozostało 580 znaków

2011-09-24 21:20

Rejestracja: 12 lat temu

Ostatnio: 7 miesięcy temu

4

user image


Women were the reason I became a monk - and, ah, the reason I switched back...

Pozostało 580 znaków

2011-09-24 22:26

Rejestracja: 16 lat temu

Ostatnio: 57 minut temu

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;
  }
przecież to jest bardzo złe ;) - byku_guzio 2011-09-25 01:24
masz LEPSZY sposób na zwrócenie obiektu? - Azarien 2011-09-25 09:25
zwracasz zmienną lokalną przez referencję - teoretycznie w momencie jej użycia może już nie istnieć. Chyba, że się mylę? - byku_guzio 2011-09-25 09:36

Pozostało 580 znaków

Newb
2011-09-24 22:44
Newb
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;
  }
Pokaż konstruktor kopiujący, jak nie masz, to napisz. - Zjarek 2011-09-25 00:31

Pozostało 580 znaków

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