Пример 4_4_3. Базовый и наследуемый классы для работы с
Линейным списком
Файл list _ base. h // Базовый класс «Линейный список»:
// определение динамического списка и его операций
#ifndef _LIST_BASE_H // Предотвращение многократного включения файла
#define _LIST_BASE_H
#include <iostream>
using std::endl;
using std::cout;
struct ELEM // Структура для элемента списка
{
int x; // Данные (целое значение)
ELEM *next; // Указатель на следующий элемент
};
class LIST_BASE // Определение класса LIST_BASE
{
// Данные
Protected: // необходим доступ и для производных от LIST _ BASE классов;
ELEM *start;// Указатель на начало списка
// Методы
public:
// Конструктор (подставляемый метод)
LIST_BASE(void): start(NULL) // Вначале список пуст
{
cout<<"\nThe base designer is called"<<endl;
}
// Деструктор (имя совпадает с именем класса, но перед ним ставится '~').
// Деструктор автоматически вызывается, когда:
// - объект уходит из области действия;
// - завершается программа;
// - используется операция delete для объектов, размещенных операцией new;
// - явно используется вызов с полным именем деструктора.
// Деструктор не имеет параметров и возвращаемого значения!
~ LIST _ BASE (void) // Подставляемый метод
{
Del_all(); // Удаление всего списка
cout<<"\nThe base destructor has completed operation "<<endl;
system (" pause "); //ТОЛЬКО ДЛЯ ОТЛАДКИ!!!
}
void Add _ end (con st int &d); // Добавить элемент в конец списка
void Print(void); // Вывод содержимого списка на экран
void Del_all(void); // Удалить весь список
void Del_end(void); // Удалить последний элемент списка
}; // Завешение определения класса LIST_BASE
// Реализация методов класса LIST_BASE
// Добавление элемента в конец списка
void LIST _ BASE:: Add _ end (const int & d) // d - добавляемое значение
{
ELEM *temp, // Указатель на новый (добавляемый) элемент списка
* cur; // Указатель на текущий элемент
temp = new ELEM; // Динамическое размещение нового элемента
if (!temp)
{
cout<<"\n The unit of the list is not placed "<<endl;
R eturn;
}
temp->x = d; // Занесение данных
temp -> next = NULL; // Новый элемент является последним
if (! start) // Новый список (пустой)
start = temp; // Указатель на начало списка
Else
{
cur = start;
while (cur->next) // Проходим весь список от начала, пока текущий
cur = cur->next; // элемент не станет последним
cur->next = temp; // Ссылка последнего элемента на новый,
// добавляемый в конец списка
}
Return;
}
// Удаление последнего элемента списка
void LIST _ BASE:: Del _ end (void)
{
ELEM *prev, // Указатель на предпоследний элемент
*end; // Указатель на последний элемент
if (! start) // Если список пуст, вывод сообщения и возврат
{
cout<<"\n The list is empty "<<endl;
Return;
}
if (!start->next) // В списке один элемент
{
Delete start;
start = NULL;
Return;
}
end = start; // Указатель на начало списка
while (end -> next) // Поиск последнего (и предпоследнего) элемента
{
prev = end;
end = end->next; // Продвижение по списку
}
delete end; // Удаление последнего элемента
prev->next = NULL; // Бывший предпоследний элемент становится последним
Return;
}
// Вывод значений данных элементов списка на экран
void LIST_BASE:: Print(void)
{
ELEM *prn; // Указатель на печатаемый элемент
if (! start) // Если список пуст, вывод сообщения и возврат
{
cout<<"\n The list is empty "<<endl;
Return;
}
prn = start; // Указатель на начало списка
while (prn) // Проходим весь список до конца
{
cout<<prn->x<<" "; // Вывод значения данных элемента списка
prn = prn->next; // Продвижение по списку
}
cout<<endl;
Return;
}
// Удаление всего списка
void LIST_BASE:: Del_all(void)
{
if (! start) // Если список пуст, вывод сообщения и возврат
{
cout<<"\n The list is empty "<<endl;
Return;
}
while (start) // Пока в списке есть элементы
Del_end(); // удаляем последний
Return;
}
#endif _LIST_BASE_H
Файл list _2. h // Класс «Линейный список 2», наследуемый от базового
// класса «Линейный список»: определение операций
#ifndef _LIST_2_H // Предотвращение многократного включения файла
#define _LIST_2_H
#include "list_base.h" // Подключение базового класса для работы со списком
class LIST _2: public LIST _ BASE // Объявление производного класса
{
// Класс LIST_2, производный от класса LIST_BASE,
// наследует от него все его данные и методы (включая деструктор).
// Конструктор базового класса не наследуется, но при создании класса,
// наследуемого от другого класса, сначала вызывается конструктор
// для базового класса, а затем конструктор, определенный в производном
// классе (если он есть).
// Компилятор ищет конструктор базового класса по умолчанию
// (т.е. без параметров).
// Если конструктор базового класса требует параметров, то конструктор
// производного класса должен вызывать базовый конструктор, используя
// список инициализации элементов.
// При разрушении объекта деструкторы вызываются в обратном порядке
// Методы
public:
void After _ Add (int find, int add); // Добавить элемент add после элемента find
void Before_Add(int find, int add); // Добавить элемент add перед элементом find
}; // Конец объявления производного класса
// Реализация методов производного класса
// Добавление элемента add после элемента find
void LIST_2:: After_Add(int find, int add)
{
ELEM *temp=NULL, // Указатель на добавляемый элемент
*cur; // Указатель на текущий элемент
if (! start) // Если список пуст, вывод сообщения и возврат
{
cout<< "\n The list is empty "<<endl;
Return;
}
// Поиск элементов, содержащих значение find, с добавлением
// после них элемента со значением add
cur = start;
while (cur) // Проходим весь список до конца
{
if (cur -> x == find)
{ // Нужный элемент найден (он является текущим)
temp = new ELEM; // Динамическое размещение элемента
if (!temp)
{
cout<<"\n The unit of the list is not placed "<<endl;
Return;
}
temp->x = add; // Занесение данных
temp -> next = cur -> next; // Ссылка на элемент, который стоял за
//текущим
cur->next = temp; // Текущий элемент указывает на новый
cur = temp; // Новый элемент становится текущим
}
cur = cur->next; // Продвижение по списку
}
// Если нужный элемент не найден (temp=NULL), вывод сообщения
if (!temp) cout<< "\nThe element "<<find<<" is not found "<<endl;
Return;
}
// Добавление элемента add перед элементом find
void LIST_2:: Before_Add(int find, int add)
{
ELEM *temp = NULL, // Указатель на добавляемый элемент
*cur, // Указатель на текущий элемент
*prev; // Указатель на элемент, стоящий перед текущим
if (! start) //Если список пуст, вывод сообщения и возврат
{
cout<<"\n The list is empty "<<endl;
Return;
}
// Поиск элементов, содержащих значение find, с добавлением
// перед ними элемента со значением add
cur = start;
while (cur) // Проходим весь список до конца
{
if (cur -> x == find)
{ // Нужный элемент найден (он является текущим)
temp = new ELEM // Динамическое размещение элемента
if (!temp)
{
cout<< "\n The unit of the list is not placed "<<endl;
Return;
}
temp->x = add; // Занесение данных
temp -> next = cur; // Новый элемент указывает на элемент с find
// Если элемент с символом find был первым
if (cur == start) // start смещается влево (на новый элемент)
start = temp;
else // Элемент, стоящий перед cur указывает на новый
prev->next = temp;
}
prev = cur; // Продвижение текущего и предыдущего
cur = cur -> next; // элементов по списку
}
// Если нужный элемент не найден (temp=NULL), вывод сообщения
if (!temp)cout<< "\nThe element "<<find<<" is not found "<<endl;
Return;
}
#endif _LIST_2_H
Файл list_2.cpp // Тестирование классов LIST_BASE и LIST_2
// Подключение производного и базового классов
# include " list _2. h "
int main () // Тестирование
{
LIST_2 ls; // Определение списка ls
// Использование функций, унаследованных от базового класса LI S T_BASE
ls.Add_end(1); // Добавление 1 в конец списка
ls.Add_end(2); // Добавление 2 в конец списка
ls.Add_end(3); // Добавление 3 в конец списка
ls.Print(); // Вывод содержимого списка
ls.Del_end(); // Удаление последнего элемента
Ls.Print();
ls.Del_all(); // Удаление всего списка
for (int i=1; i<=2; i++) // Заполнение списка двумя пятерками
Ls.Add_end(5);
Ls.Print();
// Использование функций производного класса LIS T _2: Befor_Add, After_Add
// Добавление 3 перед 5
Ls.Before_Add(5, 3);
Ls.Print();
// Добавление 4 после 3
Ls.After_Add(3, 4);
Ls.Print();
// Добавление 4 после 2
ls.After_Add(2, 4);
Ls.Print();
system("pause");
return 0;
}
Результат работы программы:

Задания для самостоятельной работы






