定义一个模板类 MyStack
#pragma once
#include "MyUtil.h"
using namespace std;
template<class T>
class MyStack
{
public:
MyStack(int staticCapacity = 10);
~MyStack();
bool IsEmpty() const; // 检查是否为空
T& Top() const; // 返回栈顶元素
void Push(const T& item); // 入栈
void Pop(); // 出栈
private:
T *stack;
int top; // stack的top位置
int capacity; // stack的容量
};
// 这里有一个需要特别注意的地方,我在开始的时候把类里面的函数定义向通常一样,放在另一个cpp文件里
// 但是报错 : 该符号在函数 _main 中被引用
// 这里是因为我们用的是类模板
/* 当编译器看到模板定义的时候,它不立即产生代码。只有在看到用到的模板时,如果调用了函数模板或调用了类模板的对象的时候,编译器才会产生特定的模板实例。
一般而言,当调用函数的时候,编译器只需要看到函数的申明。类似的,定义类类型的对象时,类定义必须可用,但成员函数的定义不是必须存在的。
因此,应该将类定义和函数申明放在头文件中,而普通函数和类成员函数的定义放在源文件中。
但模板则不同:要进行实例化,编译器必须能够访问定义模板的源代码。
模板的具体实现被称为实例化或具体化,除非编译器实现了 export 关键字,否则将模板成员函数放置在一个独立的实现文件中将无法运行。
因为模板不是函数,不能单独编译。模板必须与特定的模板实例化请求一起使用。为此,最简单的方法是将所有模板信息放在一个头文件中。
*/
template<typename T>
MyStack<T>::MyStack(int staticCapacity) : capacity(staticCapacity)
{
if (capacity < 1)
throw "capacity must be > 0";
stack = new T[capacity];
top = -1;//此时 stack 里面是空的,将top 默认赋值为-1
}
template<typename T>
MyStack<T>::~MyStack()
{
delete[] stack;
}
template<typename T>
void MyStack<T>::Push(const T& item)
{
if (top == capacity)//当 stack 满了
{
ChangeSize1D(stack, capacity, capacity * 2); // 扩容两倍
capacity *= 2; // 扩容之后要将 capacity更新为新的容量大小
}
stack[++top] = item; // 这里先将top自加一次, 然后将 item 赋值给 stack的top位置处,入栈到顶端
}
template<typename T>
inline bool MyStack<T>::IsEmpty() const
{
return top == -1;// 当top 为-1时,栈是空的,否则不为空
}
template<typename T>
inline T& MyStack<T>::Top() const
{
if (IsEmpty())
throw "Stack is empty";
return stack[top];
}
template<class T>
void MyStack<T>::Pop()
{
if (IsEmpty())
throw "stack is empty , can not delete";
stack[top--].~T(); // 这里这个 .~T() 是当模板类型是类的时候,当将顶部元素出栈,要调用该类的析构函数,当我们把对象从数组里减少的时候,要调用析构,将对象析构
}
这里当栈空间满了,要扩大空间
#pragma once
#define min(a,b) (((a) < (b)) ? (a) : (b))
template<typename T>
void ChangeSize1D(T* &a, const int oldSize, const int newSize);
template<typename T>
void ChangeSize1D(T* &a, const int oldSize, const int newSize)
{
if (newSize < 0)
throw "New size must be >= 0";
T* temp = new T[newSize];
int number = min(oldSize, newSize);
std::copy(a, a + number, temp); // 这里 要预定义 _SCL_SECURE_NO_WARNINGS
delete [] a;
a = temp;
temp = NULL;
}
main.cpp
#include <iostream>
#include "MyStack.h"
using namespace std;
int main()
{
MyStack<int> sk(20);
cout << boolalpha << sk.IsEmpty() << endl;
sk.Push(1);
sk.Push(2);
cout << sk.Top() << endl;
sk.Pop();
cout << sk.Top() << endl;
system("pause");
return 0;
}