Задание
На основе прежде  разработанного класса управления двонапрямленим списком обеспечить возможность  хранения разнотипных данных.
 Выбор алгоритма  решения задачи
  Для  решения этой задачи надо использовать базовый класс и 2 класса-потомка в  которых все данні сделать закрытыми (для того чтобы при работе случайно не  повредить их) и методы обработки этих данных. Уместным я считаю сделать еще  один класс с методами: добавление, удаление одного или всех элементов, вывод  списка на экран, а также универсальную функцию для добавления и удаление:  функция поиска.
Описание алгоритма решения задачи
  Основа программы это функция main, поскольку в ней находится  меню пользователя из которого можно задействовать любую из функций. Меню всегда  находится на экране как в начале работы так и после окончания работы одной из  функций, завершение программы происходит при нажатии клавиши Esc.
  Удаление всего списка происходит благодаря поочередному  переходу с начала до конца списка с одновременным удалением активного элемента.
  Добавление/удаление отдельного элемента происходит в два  этапа, после того как пользователь выберет место добавления/удаление элемента,  функция поиска возвратит показатель на тот элемент который забав пользователь,  а потом функция добавления/удаление разорвет цепь и прибавит/удалит элемент.
  Функция вывода таблицы поочередно перебирает все элементы  списка и выводит список на экран.
Схему алгоритма см. здесь
  Функции tabl, find, add и  del_all полностью аналогичные функциям с лабораторной работе №7.
Описание программы - см. здесь
 Функция tabl: выводит таблицу на экран монитора в  которой отображаются все элементы списка.
 Текст программы
Head.h 
#ifndef _HEAD_H_
  #define _HEAD_H_
  #include <stdio.h>
  #include <iostream>
  #include <conio.h>
  #include <time.h>
using namespace std;
const int hr=8;
  const int NAME=19;
class Base           //базовый  класс
  {
  protected:           //защищенные  данные
  char fio[NAME+1];
  unsigned int year;
  public:              //открытые  данные
  Base *prev, *next;      //указатель на следующий и предыдущий
  virtual void  view(){}   //виртуальная функция вывода
  };
class Stud : public Base   //класс  Stud наследник от Base
  {
  char grup[10];                     //поля  группа
  unsigned int stip;                 //и стипендия
  public:
  void add(Stud *p, Base *find);     // функция добавления add 
  void  view();                       //  функция вывода
  };
class Prep : public Base               //класс  Prep наследник от Base
  {
  unsigned int stag,  zarp;           //поля stag и zarp 
  public:
  void add(Prep *p,  Base *find);     //  функция добавления add
  void view();                       //  функция вывода 
  };
class mtd                              // класс mtd, который не имеет наследования
  {
  public:                                //открытые  функции
  Base *Find(int n);                 //поиск
  void tabl();                       //вывод таблицы
  void del(Base *find);              //удаление
  void del_all();                    //удалить все
  };
  #endif
 
6.2 Func.cpp
#include "Head.h"                      //подключение файла  Head.h
int KEY, COUNT;
  Base *FIRST;
Base * mtd::Find(int n)                //реализация  функции mtd для поиска 
  {                                      //нужного  места в списке
  Base *temp;
  temp=FIRST;
  int i=0;
  Base *p;
  if (n>0)
  {
  if (temp==NULL)              //если список еще не создан 
  {
  KEY=1;
  return  temp;
  }
  else
  {
  if (n==1)               //если введена первая позиция 
  {
  KEY=1;
  return  temp;
  }
  else        //иначе введено число больше чем 1 
  {
  while  (i<n-1)     //пока не  достигнут конец списка
  {
  p=temp;
  if  (p->next==NULL)   //если уже  конец списка 
  {
                                 i=n;
  KEY=0;
  return  p;   //возврат указателя на посдедний  элемент списка 
  }
  else    //если не конец списка 
  {
  temp=p->next;
  i++;
  }
  }
  KEY=1;
  return  temp;
  }
  }
  }
  else       //иначе введено n<1 список не может быть создан 
  {
  KEY=-1;
  cout<<"Zadanoe  chislo ne vhodit v predel spiska...\a\n";
  }
  return FIRST;
  }
////////////////////////////////////////////////////////////////////////
  void Stud::add(Stud *p, Base *find)    //функция добавления в класе Stud 
  {
  if (KEY>=0) // если key>=0 тогда можна добавить список 
  {
  if (find==NULL)   //если списка еще нет 
  {
  p->prev=NULL;
  FIRST=p;
  p->next=NULL;
  }
  else
  {
  if  (KEY==0)       //если  список достигнут конца
  {
  p->prev=find;
  p->next=NULL;
  find->next=p;
  }
  else              //иначе позиция не достигла  конца
  {
  if  (find==FIRST!=NULL) //если fin==first!=0 то это первый список 
  { 
  p->prev=NULL;
  p->next=FIRST;
  find->prev=p;
  FIRST=p;
  }
  else
  {
  if  (find!=FIRST) //это не первый список. Добавлять нужно в середине 
  {                 //списка 
  p->prev=find->prev;
  p->next=find;
  p->prev->next=p;
  find->prev=p;
  }
  }
  }
  }
  }
  srand(unsigned(time(NULL)));
  int  y,s,flag=0,key=0;
  char ch;
  cout<<"1.  Vvesti FIO\n";
  cout<<"2.  Sgenerirovat' FIO\n\n";
  while (!key)
  {
  key=0;
  ch=getch();
  switch(ch)  //выбор ввода данных: вручную или  сгенерировать
  {
  case '1':
  cout<<"Vvedite  FIO ";
  cin>>fio;
  cout<<endl;
  key=1;
  break;
  case '2':
  for  (s=0;s<NAME;s++)
  fio[s]=char((rand()%26)+64);
  fio[s]='\0';
  key=1;
  break;
  }
  }
  year=(rand()%10)+1980;
  for  (s=0;s<10;s++)
  grup[s]=char((rand()%26)+64);
  grup[s]='\0';
  stip=(rand()%300)+500;
  }
////////////////////////////////////////////////////////////////////////
  void Prep::add(Prep *p, Base *find)    //функция добавления в класе Prep
  {                                      // аналогичная  функция добавления в класе Stud 
  if (KEY>=0)
  {
  if (find==NULL)
  {
  p->prev=NULL;
  FIRST=p;
  p->next=NULL;
  }
  else
  {
  if  (KEY==0)
  {
  p->prev=find;
  p->next=NULL;
  find->next=p;
  }
  else
  {
  if  (find==FIRST!=NULL)
  {
  p->prev=NULL;
  p->next=FIRST;
  find->prev=p;
  FIRST=p;
  }
  else
  {
  if  (find!=FIRST)
  {
  p->prev=find->prev;
  p->next=find;
  p->prev->next=p;
  find->prev=p;
  }
  }
  }
  }
  }
  srand(unsigned(time(NULL)));
  int  y,s,flag=0,key=0;
  char ch;
  cout<<"1.  Vvesti FIO\n";
  cout<<"2.  Sgenerirovat' FIO\n\n";
  while (!key)
  {
  key=0;
  ch=getch();
  switch(ch)
  {
  case '1':
  cout<<"Vvedite  FIO ";
  cin>>fio;
  cout<<endl;
  key=1;
  break;
  case '2':
  for  (s=0;s<NAME;s++)
  fio[s]=char((rand()%26)+64);
  fio[s]='\0';
  key=1;
  break;
  }
  }
  year=(rand()%45)+1940;
  stag=2009-year-25;
  zarp=(rand()%300)+500;
  }
 
////////////////////////////////////////////////////////////////////////
  void mtd::tabl()     // вывод таблицы на экран
  {
  Base *temp;
  temp=FIRST;
  int key=1,x=0;
  if (FIRST!=NULL)
  {
  printf("  -------------------------------------------------------------\n");
  printf("|     |        |      |      |           |          |            |\n");
  printf("|  No |    FIO  | Year | Stag |  Gryppa   | Zarplata | Stipendia |\n");
  printf("|-----|-------|------|------|----------|----------|-----------|\n");
  while (key)
  {
  ++x;
  printf("|%5d|",x);
  temp->view();
  cout<<endl;
  if  (temp->next==NULL)
  key=0;
  else
  temp=temp->next;
  }
  printf("  ----------------------------------------------------------\n\n");
  }
  else
  cout<<"\nNe  zadano kolichestvo rabochih\n";
  }
////////////////////////////////////////////////////////////////////////
  void Stud::view()    //функция  выводу информации о студентах
  {
  printf("%20s|%6d|      |%10s|          |%11d|",fio,year,grup,stip);
  }
////////////////////////////////////////////////////////////////////////
  void Prep::view()    //функция  выводу информации о преподавателях
  {
  printf("%20s|%6d|%6d|          |%10d|           |",fio,year,stag,zarp);           
  }
////////////////////////////////////////////////////////////////////////
  void mtd::del_all()  //функция  удалить все
  {
  Base *p;
  int flag=1;
  if (FIRST!=NULL)
  {
  if (flag!=0)
  {
  p=FIRST;
  if  (p->next==0)
  flag=0;
  else
  FIRST=p->next;
  delete p;
  }
  }
  FIRST=NULL;
  }
////////////////////////////////////////////////////////////////////////
  void mtd::del(Base *find)  //функция  удались 1 элемент списка
  {
  Base *p, *temp;
  if (KEY>=0)
  {
  if (find==0)      //если список пуст, то нечего  удалять 
  {
  cout<<"Spisok  pyst!\n";
  getch();
  }
  else
  {
  if  (KEY==0)    //если в  списке нет такого элемента 
  {
  cout<<"Takogo  elementa nety v spiske!";
  getch();
  }
  else
  {
  if  (find==FIRST!=0)    //если это  первый элемент 
  {
  if  (FIRST->next==0)   //и если он  последний 
  {
  p=FIRST;
  delete  p;
  FIRST=0;
  }
  else    //иначе он не последний
  {
  p=FIRST;
  FIRST=p->next;
  FIRST->prev=0;
  delete  p;
  }
  }
  else         //если это не первый элемент 
  {
  if  (find!=FIRST)  
  {
  p=find;
  if  (p->next==0)  //если он  последний 
  {
  p->prev->next=0;
  delete  p;
  }
  else    //иначе он не последний 
  {
  find->prev->next=p->next;
  p->next->prev=find->prev;
  delete  p;
  }
  }
  }
  }
  }
  }
  }
 
6.3 Main.cpp
#include "Head.h"
extern Base *FIRST;
  mtd *fun;
void main(void)
  {
  mtd *p;
  p=new mtd;
  int end=0;
  char ch;
  while(!end) //пока не нажата клавиша ESC
  {
  system("cls");
  cout<<"1.   Dobavit' v spisok\n";
  cout<<"2.   Pokazat' spisok\n";
  cout<<"3.   Ydalit' element\n";
  cout<<"4.   Ydalit' spisok\n";
  cout<<"Esc.  Exit\n";
  ch=getch();
  switch (ch) // оператор  выбора
  {
  case '1':
  system("cls");
  cout<<"1.  Stydent\n";
  cout<<"2.  Prepodavatel'\n";
  int n;
  char chr;
  chr=getch();
  switch  (chr)
  {
  case '1':
  cout<<"\nVvedite  piziciy - ";
  cin>>n;
  Stud  *s;
  s=new  Stud;
  s->add(s,  p->Find(n));
  break;
  case '2':
  cout<<"\nVvedite  piziciy - ";
  cin>>n;
  Prep  *pr;
  pr=new  Prep;
  pr->add(pr,  p->Find(n));
  break;
  }
  break;
  case '2':
  system("cls");
  if  (FIRST)
  p->tabl();
  else
  cout<<"Spisok  pyst...\n";
  getch();
  break;
  case '3':
  system("cls");
  if  (FIRST)
  {
  cout<<"\nVvedite  nomer elementa - ";
  cin>>n;
  p->del(p->Find(n));
  }
  else
  {
  cout<<"Spisok  pyst...\n";
  getch();
  }
  break;
  case '4':
  system("cls");
  if  (FIRST)
  p->del_all();
  else
  {
  cout<<"Spisok  pyst...\n";
  getch();
  }
  break;
  case 27:    //выход из программы
  end=1;
  break;
  }
  }
  p->del_all();     //освобождение динамической памяти
  delete p;
  }
 
 Результат  работы программы

 
