Another C++ UB

Content:

Original link: Omit a virtual destructor / LinkedIn.

He is correct. The C++ standard says:

In the first alternative (delete object), if the static type of the object to be deleted is different from its
dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
static type shall have a virtual destructor or the behavior is undefined. 
so it is UB.

It is quite common for compiler to just not call the child class destructor.

To test your C++ compiler:


#include 

using namespace std;

class P1
{
protected:
    const char *lbl;
public:
    P1(const char *lbl)
    {
        this->lbl = lbl;
        cout << "  class P1 instance " << lbl << " allocating" << endl;
    }
    ~P1()
    {
        cout << "  class P1 instance " << lbl << " deallocating" << endl;
    }
};

class C1 : public P1
{
public:
    C1(const char *lbl) : P1(lbl)
    {
        cout << "  class C1 instance " << lbl << " allocating" << endl;
    }
    ~C1()
    {
        cout << "  class C1 instance " << lbl << " deallocating" << endl;
    }
};

class P2
{
protected:
    const char *lbl;
public:
    P2(const char *lbl)
    {
        this->lbl = lbl;
        cout << "  class P2 instance " << lbl << " allocating" << endl;
    }
    virtual ~P2()
    {
        cout << "  class P2 instance " << lbl << " deallocating" << endl;
    }
};

class C2 : public P2
{
public:
    C2(const char *lbl) : P2(lbl)
    {
        cout << "  class C2 instance " << lbl << " allocating" << endl;
    }
    virtual ~C2()
    {
        cout << "  class C2 instance " << lbl << " deallocating" << endl;
    }
};

int main()
{
    cout << "C1 = new C1:" << endl;
    C1 *a = new C1("a");
    delete a;
    cout << "P1 = new C1:" << endl;
    P1 *b = new C1("b");
    delete b;
    cout << "C2 = new C2:" << endl;
    C2 *c = new C2("c");
    delete c;
    cout << "P2 = new C2:" << endl;
    P2 *d = new C2("d");
    delete d;
    return 0;
}

Comments: