#include <iostream>
using namespace std;

class ArrayException : public Exception
{
public:
    void report()
    {
        cerr << "Array exception" << "\n";
    }
};

class MyArray
{
private:
    int m_data[5];
public:
    int & operator [] (const int & index)
    {
        //if (index < 0 || index >= 5) throw -1; // classs 안에서도 예외를 throw 가능
        //if (index<0 || index >= 5) throw Exception();
        if (index<0 || index >= 5) throw ArrayException();
        
        return m_data[index];
    }
};



void doSomething()
{
    MyArray my_array;
    
    try
    {
        my_array[100];
    }
    catch (const int & x)
    {
        cerr << "Exception" << x << "\n";
    }
    //catch (ArrayException & e)
    //{
    //    cout << "doSomething" << "\n";
    //    e.report(); // 역시나 Exception의 report() 함수 실행됨(맨 아래에 있으면). Exception 위에 놓으면 ArrayException이 실행된다.
    //    throw e; // re-throw. 다시 e를 던져서 main문에서 catch함.
    //}
    catch (Exception & e)
    {
        e.report(); // Exception 안에 report란 함수 활용
        			// catch에서 Exception만 받기때문에 받아주긴하지만 (상속구조때문에) Exception의 report 함수가 실행된다.
        //throw e; // main문에서 Exception으로 받는다.
        throw; // main문에서 ArrayException으로 받는다. 객체 잘림이 발생하지 않음.
    }
    
}

int main(
{
    try
    {
    	doSomething();
    }
    catch (ArrayException & e) // doSomething 안에서 catch가 되기때문에 이 부분은 실행되지 않음.
    {
        cout << "main()" << "\n";
        e.report();
    }
    catch (Exception & e) // 
    {
        cout << "main()" << "\n";
        e.report();
    }
	return 0;
}