#include <iostream>
class Base
{
public:
    Base() {}
    
    friend std::ostream& operator << (std::ostream &out, const Base &b) // friend는 멤버가 아니므로 override 불가능
    {
        return b.print(out); // 그래서 print 멤버를 만들고 일을 얘한테 다 시킴.
    }
    
    virtual std::ostream& print(std::ostream& out) const
    {
        out << "Base";
        return out;
    }
};

class Derived : public Base
{
public:
    Derived() {}
    
    virtual std::ostream& print(std::ostream& out) const override // 얘만 override 한다면 Base 클래스에서 << 오퍼레이터 연산 가능
    {
        out << "Derived";
        return out;
    }
};

int main()
{
    
    Base b;
    std::cout << b << "\n"; // Base 출력
    
    Derived d;
    std::cout << d << "\n"; // Derived 출력
    
    Base &bref = d;
    std::cout << bref << "\n"; // Derived 출력
    
    return 0;
}