#include <iostream>
#include <cstdint>

// Helper function: Get the current vtable pointer value of an object (assumes vptr is the first member, non-standard but works with mainstream compilers)
void* get_vptr(void* obj) {
    // Get object address, dereference to get first member (vptr pointer)
    return *reinterpret_cast<void**>(obj);
}

class Base {
public:
    Base() {
        std::cout << "Base constructor: vtable pointer = " << get_vptr(this) 
                  << " -> calling virtual function: ";
        f();  // At this point vtable points to Base's vtable, so calls Base::f
    }

    virtual ~Base() {
        std::cout << "Base destructor: vtable pointer = " << get_vptr(this) 
                  << " -> calling virtual function: ";
        f();  // Before destructor starts, vtable has switched back to Base's vtable, so calls Base::f
    }

    virtual void f() {
        std::cout << "Base::f()\n";
    }
};

class Derived : public Base {
public:
    Derived() {
        std::cout << "Derived constructor: vtable pointer = " << get_vptr(this) 
                  << " -> calling virtual function: ";
        f();  // At this point vtable has switched to Derived's vtable, calls Derived::f
    }

    ~Derived() override {
        std::cout << "Derived destructor: vtable pointer = " << get_vptr(this) 
                  << " -> calling virtual function: ";
        f();  // At the beginning of destructor, vtable is still Derived's vtable, calls Derived::f
    }

    void f() override {
        std::cout << "Derived::f()\n";
    }
};

int main() {
    std::cout << "=== Creating Derived object ===\n";
    Derived d;

    std::cout << "\n=== Calling virtual function through Base pointer (after object is fully constructed) ===\n";
    Base* ptr = &d;
    ptr->f();  // Polymorphic call: Derived::f

    std::cout << "\n=== Manual destructor (automatic destructor when leaving scope) ===\n";
    // Automatic destruction order: ~Derived() -> ~Base()
    // We can observe output before program ends, no need to call delete explicitly
    // For clarity, add another separator
    std::cout << "\n=== About to leave main, object will be automatically destructed ===\n";
    return 0;
}

results matching ""

    No results matching ""