#include<iostream>
using namespace std;
template<typename T> class Stack
{
public:
Stack(int size=10):mystack(new T[size]),
size(size),
topindex(0)
{}
//由于Stack的mystack成员变量的内存在堆上,所以不能使用编译器提供的拷贝构造函数和赋值重载函数,不然会进行浅拷贝
Stack(const Stack<T>& otherstack)//拷贝构造函数
{
size = otherstack.size;
topindex = otherstack.topindex;
mystack = new T[size];
/*
* 这里不能使用memcpy函数,因为T可能是一个对象类型
*如果用memcpy函数,就会不断进行浅拷贝构造对象,后面析构就可能出问题
*/
for (int i = 0; i < topindex;i++)//
{
mystack[i] = otherstack.mystack[i];
}
}
/*
*返回值类型是Stack而不是void,是因为要满足连续赋值s1=s2=s3
*引用则是减少了临时变量创建的开销,直接传递地址
*/
Stack& operator=(const Stack<T>& otherstack) //赋值运算符
{
if (&otherstack == this)return *this;//防止自赋值,Stack s1;s1=s1;
//释放调用这个Stack对象本来占用的那块堆空间
delete[]mystack;
size = otherstack.size;
topindex = otherstack.topindex;
mystack = new T[size];
for (int i = 0; i < topindex; i++)
{
mystack[i] = otherstack.mystack[i];
}
return *this;
}
~Stack()
{
delete[]mystack;
mystack = nullptr;
}
void push(T val)
{
if (full())expand();
mystack[topindex++] = val;
}
void pop()
{
if (empty())throw "Stack is empty";
topindex--;
}
//对于只进行只读操作的函数一般都要声明为常成员函数,这样一般的对象和常对象都可以调用这个函数
T top()const//这里不调用empty函数,是因为一般用户使用top函数的时候就会配合empty函数一起使用
{
return mystack[topindex - 1];
}
bool full()const
{
return size == topindex;
}
bool empty()const
{
return topindex == 0;
}
private:
T* mystack;
int size;
int topindex;
void expand()//将这个函数声明为private,是因为扩容是Stack类的内部操作用于自动扩容,用户不需要调用
{
T* newstack = new T[size * 2];
for (int i = 0; i < topindex; i++)
{
newstack[i] = mystack[i];
}
delete[]mystack;
mystack = newstack;
}
};
int main()
{
Stack<int> s;
srand(time(NULL));
for (int i = 0; i < 10; i++)
{
s.push(rand() % 100);
}
while (!s.empty())
{
cout << s.top()<<" ";
s.pop();
}
return 0;
}
C++通过类模板实现一个可以容下各种对象的万物栈
于 2024-08-09 22:59:44 首次发布