Dziedziczenie a destruktor

Dziedziczenie a destruktor
R3
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 50
0

Witam,
Podczas pracy nad programem napotkałem pewien błąd, który powoduje krytyczny wyjątek programu. Udało mi się go zlokalizować: destruktor klasy.

By lepiej zobrazować problem posłużę się przykładem.

Kopiuj
 
class CRectangle {  //klasa prostokata
  private:
    unsigned lenb;  //dlugosc boku b  

  protected:
     SPoint *pnt;     //punkt poczatkowy prostokatu (gorny lewy rog)
     unsigned lena;  //dlugosc boku a
     (...)
  public:
     (...)
     ~CRectangle() {
       if (pnt != NULL) delete pnt;
     }
     (...)
}

class CSquare : public CRectangle { //klasa kwadratu
    //wszystkie obiekty dziedziczone po prostokacie
    
  public:
    (...)
    ~CSquare()  {
      if (pnt != NULL) delete pnt; //tutaj pojawia sie problem!
    }
    (...)
}

Powyższy kod skutkuje błędem. Usunięcie destruktora klasy CSquare załatwia problem - wszystko działa bez zarzutu. I stąd moje pytanie: czy jeśli dziedziczę obiekt X z innej klasy to usuwając daną klasę, X jest usuwany korzystając z destruktora klasy bazowej?

Flaker
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 98
1

Niszczenie obiektu działa analogicznie do tworzenia go, lecz w drugą stronę:
Gdy konstruowany jest obiekt, najpierw wywoływany jest konstruktor klasy bazowej, i dopiero potem klas dziedziczących z niej.
Przy niszczeniu działa to w drugą stronę, dlatego też próba dwukrotnego zwolnienia pamięci kończyła się błędem w Twoim przypadku.

ŁF
  • Rejestracja: dni
  • Ostatnio: dni
0

btw po zwolnieniu pamięci wskaźnik do niej powinieneś ustawić na null. wtedy nie miałbyś powyższego problemu.

43
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 61
0

Po pierwsze i najważniejsze.

NIGDY:
if (pnt != NULL) { delete pnt; }

ZAWSZE!!!
if (pnt != NULL) { delete pnt; pnt = NULL; }

Po drugie:
Jeśli klasa A dziedziczy z B, przed wywołaniem destruktora A zostaje wywoływany destruktor B.
I w tym momencie wchodzi filozofia OOP. Jeśli jakieś pole należy do klasy bazowej ( prostokąt ), nie należy w nie ingerować z klasy, która dziedziczy.

Współrzędne wierzchołków ( SPoint ) są własnością prostokąta ( czy - ogólniej - czworokąta ). Kwadrat, w momencie "się usuwania" "wie", że prostokąt został już usunięty. Wierzchołki należą do prostokąta ( czy nawet jeszcze dalszej klasy bazowej, z której dziedziczy prostokąt ) - nie powinien więc nawet próbować ich usuwać.

VL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
2

Po pierwsze i najważniejsze: kwadrat dziedziczy po prostokącie??? Naprawdę? Jeżeli ktoś Cię tak nauczył, to zmień nauczyciela. To jakaś masakra. Bazowa klasa figury i dziedziczące po nim konkretne figury. To typowy test na OOP.

Po drugie i może jeszcze ważniejsze: jeżeli dziedziczenie wchodzi w grę to destruktor bazowej virtual.

AF
  • Rejestracja: dni
  • Ostatnio: dni
0
4ggr35510n napisał(a):

Po pierwsze i najważniejsze.

NIGDY:
if (pnt != NULL) { delete pnt; }

ZAWSZE!!!
if (pnt != NULL) { delete pnt; pnt = NULL; }

Można pominąć ifa - kasowanie nulla nie powoduje błędu.

byku_guzio
  • Rejestracja: dni
  • Ostatnio: dni
0

Aktualnie jeszcze lepiej zamiast pnt = NULL; dać pnt = nullptr;

VL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

Jak już zostało zauważone - to miało tylko wskazać pewną złą praktykę.

Ważniejsza kwestia to wirtualny destruktor klasy bazowej.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.