#include <iostream>

struct base
{
    virtual void print_type() const {
        std::cout << "base\n";
    }
};

struct derived : public base
{
    void print_type() const {
        std::cout << "derived\n";
    }
};

int main()
{
    base b; // b is an object of type base.  It can never be anything else.
    b.print_type();

    derived d;
    d.print_type();

    b = d; // If we set b equal to an object of type derived, it is still an object of type base.
    b.print_type();

    base* ptr = &b;     // ptr is a pointer to some class in the base hierarchy
    ptr->print_type();  // if we point it a a base class object, we get base class behavior

    ptr = &d;           // if we point it a derived class object, we get derived class behavior
    ptr->print_type();
}