#include <iostream>
#include <cstdint>
using namespace std;

#define  w(expr)  cout << #expr << ": " << expr << endl;

struct M {
    M(uint64_t x) : m{x} { cout << "M::M(uint64_t)" << endl; }
    ~M() { cout << "M::~M()" << endl; }
    uint64_t m;
};

struct B {
    B(uint64_t x) : b{x} { cout << "B::B(uint64_t)" << endl; }
    ~B() { cout << "B::~B()" << endl; }
    // virtual uint64_t sum() const = 0;
    uint64_t b;
};

struct D : public B {
    D() : B{100}, m_obj{200}, d{300} { cout << "D::D()" << endl; }
    ~D() { cout << "D::~D()" << endl; }
    // uint64_t sum() const override { return b + m_obj.m + d; }
    M m_obj;
    uint64_t d;
};

int main() {
    cout << "*** Order of construction and destruction" << endl;
    {
        D x;
        // B y;  // Compilation error
        // B* bp = &x;
        // w( bp->sum() );
    }

    // cout << "*** Virtual destructor" << endl;

    // Observe the change in output when you:
    // - change B::~B() to virtual
    // - override in D::~D().

    // B* pb = new D;
    // delete pb;
}
