/****************************************************************
  Filename:  mi6.cpp
  Compiler:  Borland C++     Version 5.1      Summer 1997
  Ira Pohl  Copyright May 1997

  Multiple inheritance mixin example
  implementation + interface
  
  See pp342-347 Section 10.7 Object-Oriented Programming Using C++, 2nd Edition
  See p93 Section 12.1 C++ Distilled 
  See p270-275 Section 7.7 C++ for Pascal Programmers, 2nd Edition
  See p336-338 Section 9.6 C++ for Fortran Programmers 

*****************************************************************/

#include < iostream.h>
#include < deque>
using namespace std;

//Abstract base Class provides interface specifications
//Note this is a small interface
//Exercise extend the interface to include other standard
//stack operations. Then extend the derived classes as well
//and test with examples in main().

template< class T>
class stack{
public:
   virtual void push(T i)=0;
   virtual T pop()=0;
};

//An implementation class
template< class T>
class array{
public:
   array(int n = 100): size(n), s(new T[n]){}
protected:
   T* s;
   int size;
};

//An implementation class  using STL
template< class T>
class mylist{
public:
   mylist(int n = 100): size(n), s(new deque< T>(n)){}
protected:
   deque< T>* s;
   int size;
};

//mixin - interface(public) + implementation(private)
template< class T>
class list_stack: public stack< T>, private mylist< T>{
public:
   list_stack(int n = 100): mylist< T>(n), top(-1){}
   void push(T i){(*s)[++top] = i;}
   T pop(){return (*s)[top--]; }
private:
   int top;
};

template< class T>
class array_stack: public stack< T>, private array< T>{
public:
   array_stack(int n = 100):array< T>(n), top(-1){}
   void push(T i){s[++top] = i;}
   T pop(){return s[top--]; }
private:
   int top;
};

int main()
{
   cout << " stack via mi " << endl;
   list_stack< int> w(1000);
   array_stack< char> x(1000);
   w.push(9); w.push(8); w.push(7);
   cout << "pop " << w.pop() << endl;
   cout << "pop " << w.pop() << endl;
   x.push('b'); x.push('c'); x.push('h');
   cout << "pop " << x.pop() << endl;
   cout << "pop " << x.pop() << endl;
}