Dziedziczenie i polimorfizm

0

Mam napisane 3 klasy w 6 plikach:

klasabaza.h

#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

#include "klasabaza.h"

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

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

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

klasa1.h

#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

#include "klasa1.h"

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

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

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

klasa2.h

#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

#include "klasa2.h"

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

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

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

Wywołanie:

    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:

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:

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:

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:

    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:

    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.

2

Destruktor klasy bazowej musi być wirtualny

virtual ~KlasaBaza();
0

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

1

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

1

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

0

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

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