#include <iostream>
using namespace std;

class Base
{
protected:
	int m_i;

public:
	Base(int value)
		: m_i(value)
	{}
	
	void print()
  {
    cout << "I'm base" << "\n";
  }
  
  friend std::ostream & operator << (std::ostream & out, const Base &b)
  {
    cout << "This is base output" << "\n";
    return out;
  }
};

class Derived : public Base
{
private:
  double m_d;
  
public:
  Derived(int value)
    : Base(value)
  {}
  
  void print()
  {
    Base::print(); // 와 같이 Base의 print를 호출하고 Derived의 print에 추가로 기능을 구현할 수 있다.
    // 만약 print(); 라고 단순히 적는다면 무한재귀호출이 된다.
    cout << "I'm Derived" << "\n";
  }
  
  friend std::ostream & operator << (std::ostream & out, const Derived &b)
  {
    // Base::operator << ?????  //. 위의 print와 같이 base를 호출하고싶다 
    cout << static_cast<Base>(b) << "\n"; // b를 Base로 static cast시킨뒤 cout 한다.
    
    cout << "This is Derived output" << "\n";
    return out;
  }
  
};

int main()
{
  Base base(5);
  // base.print();
  cout << base;
  
  Derived derived(7);
  //derived.print();
  cout << derived;
  
  return 0;
}