// 自定义标准异常类
#include <iostream>
#include <exception>

using namespace std;

class OutOfRangeError : public exception
{
public:
    virtual const char *what() const throw()
    {
        return "访问索引越界";
    }
};

template <typename T>
class Stack
{
private:
    T *mData;      // 数据
    int mCapacity; // 容量
    int mIndex;    // 索引

public:
    // -1 表示栈为空
    Stack(int capacity) : mCapacity(capacity), mIndex(-1)
    {
        this->mData = new T[this->mCapacity];
    }
    ~Stack()
    {
        delete[] this->mData; // 释放内存
        mData = nullptr;      // 防止野指针
    }

public:
    T pop() throw(OutOfRangeError)
    {
        if (mIndex < 0)
            throw OutOfRangeError();
        return this->mData[this->mIndex--];
    }
    Stack<T> &push(const T &item) throw(OutOfRangeError)
    {
        if (mIndex >= mCapacity - 1) // >= 表示栈满 , mCapacity - 1 表示栈顶
            throw OutOfRangeError();
        this->mData[++this->mIndex] = item;
        return *this; // 返回当前对象，支持链式编程
    }
    T &at(int index) throw(OutOfRangeError)
    {
        // mIndex == -1 表示栈为空，index < 0 表示索引小于 0，index > mIndex 表示索引大于栈顶
        if (mIndex == -1 || index < 0 || index > mIndex)
            throw OutOfRangeError();
        return this->mData[index];
    }
    int size() const
    {
        return this->mIndex + 1;
    }
};

int main()
{
    Stack<int> s1(5);
    s1.push(10).push(20).push(30);
    for (int i = 0; i < s1.size(); i++)
        cout << s1.at(i) << endl;

    cout << "*** 弹出数据 ***" << endl;
    // 清空数据
    while (1)

    {
        try
        {
            cout << s1.pop() << endl;
        }
        catch (exception &e)
        {
            cout << "error: " << e.what() << endl;
            break; // 异常处理: 跳出循环
        }
    }

    cout << "*** 弹栈完成，重新打印 ***" << endl;
    for (int i = 0; i < s1.size(); i++)
        cout << s1.at(i) << endl;

    return 0;
}
