2

Can any one explain how delete x works correctly without virtual ~X()

#include <iostream>

struct B
{
    B()
    {
        std::cout << "B()" << std::endl;
    }
    virtual ~B()
    {
        std::cout << "~B()" << std::endl;
    }
};

struct C : B
{
    C()
    {
        std::cout << "C()" << std::endl;
    }
    virtual ~C()
    {
        std::cout << "~C()" << std::endl;
    }
};

template <class T>
struct X : T
{
    X()
    {
        std::cout << "X()" << std::endl;
    }
    ~X()
    {
        std::cout << "~X()" << std::endl;
    }
};

template <class T>
struct Y : X<T>
{
    Y()
    {
        std::cout << "Y()" << std::endl;
    }
    ~Y()
    {
        std::cout << "~Y()" << std::endl;
    }
};

int main()
{
    std::cout << "====" << std::endl;
    {
        B* b = new C;
        delete b;
    }
    std::cout << "====" << std::endl;
    {
        X<C>* x = new Y<C>;
        delete x;
    }
    std::cout << "====" << std::endl;
    return 0;
}

Output:

====
B()
C()
~C()
~B()
====
B()
C()
X()
Y()
~Y()
~X()
~C()
~B()
====
Midori Yakumo
  • 184
  • 12

1 Answers1

5

It is virtual – X<C> inherits C, the root of the hierarchy is B, and the destructor is declared virtual in B.

The class templating is completely irrelevant; it works exactly as it would if you had

struct X : C
{
    X() { std::cout << "X()" << std::endl; }
    ~X() { std::cout << "~X()" << std::endl; }
};

struct Y : X
{
    Y() { std::cout << "Y()" << std::endl; }
    ~Y() { std::cout << "~Y()" << std::endl; }
};

and

X* x = new Y;
delete x;
molbdnilo
  • 64,751
  • 3
  • 43
  • 82