Пример: Класс, описывающий базовый класс списка и производный класс стека

 

#include <iostream>

#include <conio.h>

#include <windows.h>

#include <assert.h>

using namespace std;

// класс, описывающий один узел :

class ListItem

{

int data;

ListItem *next, *prev;

 

friend class List;

friend class Stack;

 

int Get() { return data; }

friend ostream& operator << (ostream&, List*);

friend istream& operator >> (istream&, List*);

public:

ListItem(const int d) // конструктор

{

data = d;

next = prev = NULL;

}

};

 

// Базовый класс списка:

class List

{

protected:

ListItem *back, *front, *token;

 

friend ostream & operator<<(ostream&, List*);

friend istream & operator>>(istream&, List*);

 

public:

List() {back = front = token = NULL;}

~List();

void PutToken(int); // добавляет элемент в список

virtual int GetToken(); // считывает текущий элемент списка

BOOL empty() {return front == NULL ? true:false;}

};

 

//Производный класс:

class Stack: public List

{

/* Стек является частным случаем списка и отличается главным образом тем, что удаление данных выполняется с конца. Будем считать, что при чтении данных стека, элементы данных удаляются (чтение с разрушением) */

int GetToken(); //считывает данные из стека

};

//---------------------------------------------------------------

//определение функций:

 

void List :: PutToken(int val)

{

ListItem *p = new ListItem(val);

if(empty()) front=back=p;

else

{

back->next = p; p->prev=back; back=p;

}

}

//----------------------------------------------------

int List :: GetToken()

{

if (token == NULL) token = front;

if (token)

{

int rv = token->data;

token = token->next;

return rv;

}

else return 0;

}

//---------------------------------------------------

ostream& operator << (ostream& os, List* q)

{

os<<"< ";

do

if (! q->empty())

os << q->GetToken() << ",";

while (q->token);

return os << ">" << endl;

}

//----------------------------------------------------------

istream & operator >> (istream &is, List* q)

{

int a; int k;

cout<<"Сколько элементов будете вводить? ";

is>>k;

for(int i=0; i<k; i++)

{

cout << i+1 << ": "; is >> a;

q->PutToken(a);

}

return is;

}

 

int Stack :: GetToken()

//Удаляет элемент c конца списка

{

if (token == NULL) token = back;

if (back)

{

back = back->prev; //Следующий элемент становится первым

if (back)

{ back->next = NULL; }

else front = NULL;

int retval = token->data;

delete token;

token = back;

return retval;

}

else return 0;

}

//--------------------------------------------------------------

 

int main()

{

//Настройки шрифтов и региональных стандартов:

if(SetConsoleCP(1251)==0)

//проверка правильности установки кодировки символов для ввода

{

cerr<<"Fialed to set codepage!"<<endl;

/* если не удалось установить кодовую страницу, вывод сообщения об ошибке */

}

if(SetConsoleOutputCP(1251)==0)//тоже самое для вывода

{

cerr<<"Failed to set OUTPUT page!"<<endl;

}

List* lst = new List;

cin >> lst;

cout<<"Список:\n";

cout << lst;

cout<<"Повторный вывод списка:\n";

cout << lst;

List* st; // Обратите внимание на тип указателя

st = new Stack;

cin >> st;

cout<<"Стек:\n";

cout << st; //Удаляет элемент c "хвоста"

cout<<"Повторный вывод стека:\n";

cout << st; // стек уже пуст

_getch();

return 0;

}