標籤:style class blog code color strong
說明:本文僅供學習交流,轉載請標明出處,歡迎轉載!
一提到適配器(adapter),我們就想到了早期用電話線上網所用的數據機,俗稱“貓”,“貓”的作用是實現數模轉化和模數轉化,在用戶端,它可以將電話的類比資訊轉化為我們電腦能夠接收的數字資訊,所以貓相當於一個轉換器。再舉個更加好理解的例子來說明"適配器“的含義。相信在我們每個人的家裡都有插排,假設就這麼一種情況,現在我們家裡的牆壁上只有一個三角的插口,而我們的電視卻是兩個口,怎麼辦?毫無疑問,我們可以接一個新的插排,該插排至少有兩個孔,一個是用於串連牆壁上的三角的插口,一個則是提供給電視劇用的兩口的插口。這樣,我們就可以將新加入的中間用於轉換的插排是一個適配器。
從上面的例子我們可以很容易的得出:適配器能夠對原始事物進行一次封裝與修飾,並提供另外一種介面,該介面能夠更好地滿足使用者的需求,具有一定的專用性。
這樣,我們就可以介紹下stack這一容器適配器了。之前我們已經介紹過三種基本的順序容器,分別是vector、list和deque,這三種順序容器的設計都會設計到迭代器的概念,STL要求任何一種容器都必須內建一個迭代器,如果連迭代器都沒有內建,就談不上”容器“的定義了。
學習過”資料結構“的人都知道棧,棧是一種後進先出或者說先進後出的資料結構,一個棧的插入和刪除操和取值都只能在棧頂進行,根據棧的性質,棧頂元素必然是最後一個進入的元素。根據這點,我們可以很容易地得出一個結論:任何提供末端插入(push_back函數)、刪除(pop_back函數)、訪問(back函數)都能夠被stack容器封裝與修飾。這裡的封裝指的是通過stack對象,你不能直接存取被封裝的底層容器了,所謂的修飾指的是stack在對底層容器做封裝的同時,還提供了必要的介面,以滿足使用者的需要。我們將被適配器封裝的底層容器稱為基礎容器。
在我們所學過的順序容器中,只要能夠提供末端的插入、刪除和訪問操作,都可以作為stack適配器的基礎容器,所以vector、list和deque都可以作為stack的基礎容器,而stack預設的基礎容器為deque容器。
對於一個stack,我們通常需要提供這幾個介面函數:
(1)擷取棧內當前元素的個數:size_type size();
(2)取棧頂元素(但並不彈出):T top();
(3)入棧:void push(const T &t);
(4)出棧:void pop();
(5)判斷是否棧空:bool empty()。
下面給出stack適配器的實現代碼:
#include<iostream>#include<deque>using namespace std;
/*******************stack適配器的定義**************/template<class T,class Sequence=deque<T> >class stack{friend bool operator==(const stack&,const stack&);//friend函數是全域函數,不受private的限制friend bool operator<(const stack&,const stack&);//類內聲明,類外定義,定義是不加friendpublic:typedef typename Sequence::value_type value_type;//typename型別宣告,元素類型typedef typename Sequence::size_type size_type;//大小類型typedef typename Sequence::reference reference;//引用聲明typedef typename Sequence::const_reference const_reference;//常引用聲明protected:Sequence c;//基礎的底層容器public:bool empty()const;//是否為空白size_type size()const;//大小reference top();//取頂部元素const_reference top()const;void push(const value_type &x);//壓棧void pop();//出棧};
/******************各個函數介面的類外實現**********************/template<class T,class Sequence>bool operator==(const stack<T,Sequence> &x, const stack<T,Sequence> &y)//判斷兩個適配器是否相等{return x.c==y.c;}template<class T,class Sequence>bool operator<(const stack<T,Sequence>& x,const stack<T,Sequence>& y)//判斷適配器x是否小於適配器y{return x.c<y.c;}template<class T,class Sequence>bool stack<T,Sequence>::empty()const//常成員函數類外定義需要加const關鍵字{return c.empty();}template<class T,class Sequence>//類外無需加預設形參//如果寫成size_type stack<T,Sequence>::size()const是錯誤的,因為size_type是在類內定義的,且typename最好也加上typename stack<T,Sequence>::size_type stack<T,Sequence>::size()const{return c.size();}template<class T,class Sequence>typename stack<T,Sequence>::reference stack<T,Sequence>::top()//底層實現是返回最後一個容器的元素{return c.back();}template<class T,class Sequence>typename stack<T,Sequence>::const_reference stack<T,Sequence>::top()const//top函數的重載{return c.pop_back();}template<class T,class Sequence>void stack<T,Sequence>::push(const value_type & x)//底層實現是向基礎容器的尾部添加元素{c.push_back(x);}template<class T,class Sequence>void stack<T,Sequence>::pop()//底層實現是將基礎容器的尾部元素彈出{c.pop_back();}
參考資料:
[1]《STL源碼剖析 侯捷》
[2]《C++ primer 第4版》