Dziedziczenie i polimorfizm

Dziedziczenie i polimorfizm
AN
  • Rejestracja: dni
  • Ostatnio: dni
0

Mam napisane 3 klasy w 6 plikach:

klasabaza.h

Kopiuj
#ifndef KLASABAZA_H
#define KLASABAZA_H
#include <iostream>

using namespace std;

class KlasaBaza
{
public:
    KlasaBaza();
    ~KlasaBaza();
    void MetodaWspolna();
    virtual void MetodaKlasy() = 0;
};

#endif // KLASABAZA_H

klasabaza.cpp

Kopiuj
#include "klasabaza.h"

KlasaBaza::KlasaBaza()
{
    cout << "Konstruktor KlasaBaza" << endl;
}

KlasaBaza::~KlasaBaza()
{
    cout << "Destruktor KlasaBaza" << endl;
}

void KlasaBaza::MetodaWspolna()
{
    cout << "Metoda KlasaBaza" << endl;
}

klasa1.h

Kopiuj
#ifndef KLASA1_H
#define KLASA1_H
#include <iostream>
#include "klasabaza.h"

using namespace std;

class Klasa1 : public KlasaBaza
{
public:
    Klasa1();
    ~Klasa1();
    void MetodaKlasy();
};

#endif // KLASA1_H

klasa1.cpp

Kopiuj
#include "klasa1.h"

Klasa1::Klasa1()
{
    cout << "Konstruktor Klasa1" << endl;
}

Klasa1::~Klasa1()
{
    cout << "Destruktor Klasa1" << endl;
}

void Klasa1::MetodaKlasy()
{
    cout << "Metoda Klasa1" << endl;
}

klasa2.h

Kopiuj
#ifndef KLASA2_H
#define KLASA2_H
#include <iostream>
#include "klasabaza.h"

using namespace std;

class Klasa2 : public KlasaBaza
{
public:
    Klasa2();
    ~Klasa2();
    void MetodaKlasy();
};

#endif // KLASA2_H

klasa2.cpp

Kopiuj
#include "klasa2.h"

Klasa2::Klasa2()
{
    cout << "Konstruktor Klasa2" << endl;
}

Klasa2::~Klasa2()
{
    cout << "Destruktor Klasa2" << endl;
}

void Klasa2::MetodaKlasy()
{
    cout << "Metoda Klasa2" << endl;
}

Wywołanie:

Kopiuj
    KlasaBaza *O1 = new Klasa1();
    O1->MetodaWspolna();
    O1->MetodaKlasy();
    delete O1;
    KlasaBaza *O2 = new Klasa2();
    O2->MetodaWspolna();
    O2->MetodaKlasy();
    delete O2;

Przy kompilacji są takie ostrzeżenia:

Kopiuj
E:\Develop\QT\Test2\mainwindow.cpp:21: ostrzeżenie: deleting object of abstract class type 'KlasaBaza' which has non-virtual destructor will cause undefined behaviour [-Wdelete-non-virtual-dtor]
     delete O1;
            ^
E:\Develop\QT\Test2\mainwindow.cpp:25: ostrzeżenie: deleting object of abstract class type 'KlasaBaza' which has non-virtual destructor will cause undefined behaviour [-Wdelete-non-virtual-dtor]
     delete O2;
            ^

Wyjście programu:

Kopiuj
Konstruktor KlasaBaza
Konstruktor Klasa1
Metoda KlasaBaza
Metoda Klasa1
Destruktor KlasaBaza
Konstruktor KlasaBaza
Konstruktor Klasa2
Metoda KlasaBaza
Metoda Klasa2
Destruktor KlasaBaza

Wyjście pokazuje, że nie został wywołany destruktor klasy dziedziczącej. Oczekiwałem takiego wyjścia:

Kopiuj
Konstruktor KlasaBaza
Konstruktor Klasa1
Metoda KlasaBaza
Metoda Klasa1
Destruktor Klasa1
Destruktor KlasaBaza
Konstruktor KlasaBaza
Konstruktor Klasa2
Metoda KlasaBaza
Metoda Klasa2
Destruktor Klasa2
Destruktor KlasaBaza

Założenie jest takie, że jest obiekt typu klasy bazowej i może wskazywać na obiekt dowolnej klasy dziedziczącej po tej klasie.
Poniższe wywołanie, pomimo, że poprawne, nie generuje ostrzeżeń i daje oczekiwany rezultat, nie jest zgodne z powyższym założeniem:

Kopiuj
    Klasa1 *O1 = new Klasa1();
    O1->MetodaWspolna();
    O1->MetodaKlasy();
    delete O1;
    Klasa2 *O2 = new Klasa2();
    O2->MetodaWspolna();
    O2->MetodaKlasy();
    delete O2;

Zgodne z założeniem jest jeszcze takie wywołanie, które bardziej ilustruje problem, generuje te same ostrzeżenia i nie wywołuje wszystkich destruktorów:

Kopiuj
    KlasaBaza *Obj;
    Obj = new Klasa1();
    Obj->MetodaWspolna();
    Obj->MetodaKlasy();
    delete Obj;
    Obj = new Klasa2();
    Obj->MetodaWspolna();
    Obj->MetodaKlasy();
    delete Obj;

Jak zmusić program, żeby wywoływał destruktor klasy dziedziczącej i nie było ostrzeżeń przy kompilacji. Drugim założeniem jest to, żeby zarówno destruktor klasy bazowej, jak i pochodnej wykonywał jakieś instrukcje, podobnie, jak konstruktor.

twonek
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2500
2

Destruktor klasy bazowej musi być wirtualny

Kopiuj
virtual ~KlasaBaza();
AN
  • Rejestracja: dni
  • Ostatnio: dni
0

Zmieniłem w pliku klasabaza.h, teraz nie ma ostrzeżeń, ale nadal nie uruchamiają się destruktory klas pochodnych. Co jeszcze trzeba zmienić?

twonek
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2500
1

Nic. Pewnie nie zrobiłeś clean builda albo czegoś w tym stylu.

EvilOne
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 78
1

wyczyść projekt i zbuduj raz jeszcze, a Twój program wypluje oczekiwany output: https://ideone.com/wD4pp0

AN
  • Rejestracja: dni
  • Ostatnio: dni
0

Tak, wystarczyło wyczyścić i przebudować projekt, teraz jest wszystko prawidłowo.

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.