Today again read the "Effective C + +", manual implementation of the article 42 in the stack, posted out when the blog's maiden post.
First the stack is declared as follows, the template is passed into the type, and the bottom of the stack is a linked list.
//stack.h//by Chwen 2014-10-27#include<stdio.h>#include<stdlib.h>#include<iostream>using namespacestd;//Stack DeclarationTemplate<typename t>classstack{ Public: Stack (); ~Stack (); voidPushConstt&node); T Top (); voidpop (); intSize ()Const; BOOLEmpty ()Const; voidClear ();Private: structStacknode {T data; Stacknode*Next; Stacknode (Constt& NewData, stacknode*nextnode):d ata (NewData), Next (NextNode) {}}; Stacknode*top; //prevent default copy and default assignmentStack (Conststack&RHS); Stack&operator=(Conststack&RHS); intmysize;};
and the corresponding CPP implementation is as follows:
//Stack.cpp#include"stack.h"using namespacestd;//Stack ImplementationTemplate<typename t>Stack<T>:: Stack (): Top (nullptr), Mysize (0) {}template<typename t>Stack<t>::~Stack () {clear ();} Template<typename t>voidStack<t>::p Ush (Constt&node) {Top=NewStacknode (node,top); Mysize++;} Template<typename t>T Stack<T>:: Top () {if(Empty ()) {_debug_error ("Error, Stack is empty!"); } returnTop->data;} Template<typename t>voidStack<t>::p op () {if(Empty ()) {_debug_error ("Error, Stack is empty!"); } Stacknode* Topofstack =top; Top= top->Next; Delete Topofstack; Topofstack=nullptr; Mysize--; return;} Template<typename t>BOOLStack<t>::empty ()Const{ returntop = =nullptr;} Template<typename t>voidStack<t>:: Clear () { while(top) {Stacknode* Topofstack =top; Top= top->Next; Delete Topofstack; } mysize=0;} Template<typename t>intStack<t>::size ()Const{ returnmysize;}
The above is the use of template implementation of all the code stack, you can implement the stack push, pop, top, clear and other operations.
A simple test code is written below:
void FUNV () {Stack <int > S; for (int i = 0 ; I < 10 ; ++i) {s.push (i); for (int j = s.size ()-1 ; J >= 0 ; --j) {cout << node: << s.top () <<ENDL; S.pop (); } s.clear ();}
int main ()
{
FUNV ();
GetChar ();
return 0;
}
then effective C + + points out another, more subtle way to implement it, private inheritance.
The code is implemented as follows:
//stack.h//by Chwen 2014-10-27#include <stdio.h>#include<stdlib.h>#include<iostream>classcommonstack{protected: Commonstack (); ~Commonstack (); voidPushvoid*node); void*Top (); voidpop (); intSize ()Const; BOOLEmpty ()Const; voidClear (); Private: structStacknode {void*data; Stacknode*Next; Stacknode (void* NewData, stacknode*nextnode):d ata (NewData), Next (NextNode) {}}; Stacknode*top; //prevent default copy and default assignmentCommonstack (Constcommonstack&RHS); Commonstack&operator=(Constcommonstack&RHS); intmysize;}; Template<typename t>classStack:Privatecommonstack{ Public: voidPush (T * ty) {commonstack::p ush (static_cast<void*>(Ty)); T* Top () {returnStatic_cast<t*>(Commonstack::top ());} voidPop () {returncommonstack::p op ();} intSize () {returncommonstack::size ();} BOOLEmpty ()Const{returncommonstack::empty ();} voidClear () {returncommonstack::clear ();} };
The corresponding CPP is as follows:
#include"stack.h" using namespaceStd;commonstack::commonstack (): Top (nullptr), Mysize (0) {} Commonstack::~Commonstack () {clear ();}voidCommonstack::p Ush (void*node) {Top=NewStacknode (node,top); Mysize++;} void*Commonstack::top () {if(Empty ()) {_debug_error ("Error, Stack is empty!"); } returnTop->data;} voidcommonstack::p op () {if(Empty ()) {_debug_error ("Error, Stack is empty!"); } Stacknode* Topofstack =top; Top= top->Next; Delete Topofstack; Topofstack=nullptr; Mysize--; return;} BOOLCommonstack::empty ()Const{ returntop = =nullptr;} voidcommonstack::clear () { while(top) {Stacknode* Topofstack =top; Top= top->Next; Delete Topofstack; } mysize=0;} intCommonstack::size ()Const{ returnmysize;}
Here Commonstack the original template class T to void*, and then use protected to protect the class is not called by other unknown masses, but gives a template interface class private inheritance of this class, so that, both play a protective role, In the case of low loss, it gives the easy-to-use interface and the design of the workmanship.
The test code is as follows:
voidFuncint () {int* a[Ten]; for(inti =0; I <Ten; ++i) {A[i]=New int(i); } Stack<int>s; for(intj =0; J <Ten; ++j) {S.push (a[j]); } intK =s.size (); int* t =S.top (); S.pop (); if(S.empty ()) {cout<<"Empty"<<Endl; } s.clear (); for(inti =0; I <Ten; ++i) {delete a[i]; }}voidfuncstring () {string* str[Ten]; for(inti =0; I <Ten; ++i) {Str[i]=New string("a"); } Stack<string>s; for(intj =0; J <Ten; ++j) {S.push (str[j]); } intK =s.size (); string* t =S.top (); S.pop (); if(S.empty ()) {cout<<"Empty"<<Endl; } s.clear (); for(inti =0; I <Ten; ++i) {delete str[i]; }}intMain () {funcint (); Funcstring (); GetChar (); return 0;}
The test code has no output and can see the data at breakpoints.
And then I took a look at the STL implementation of the Stack, which by default uses deque as the underlying implementation of the stack.
Template<class _ty,class _container = deque<_ty> >class stack{//Stack Implementation}
When called directly std::stack<int> is the default use of deque as the stack underlying container.
Users can also specify other ways, such as Std::stack<int, Std::list<int>, which uses the list as the underlying container for the stack.
What makes me feel awesome is that the refinement and flexibility of the STL implementation is a way to specify the underlying implementation, too ingenious. Look back to the "STL Source analysis."
Only lists the code, not too detailed introduction principle, interested can go directly to see "effective C + +" and "STL Source Analysis", as well as the STL stack code.
Quote Please specify the source, http://www.cnblogs.com/chwen/p/4055474.html very grateful, at any time to communicate.
A method of using template to implement stack in C + +