Dziedziczenie a destruktor

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.

 
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?

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.

0

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

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ć.

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.

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.

0

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

0

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

Ważniejsza kwestia to wirtualny destruktor klasy bazowej.

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