定義一個模板類 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;
}