193: {
194: PartNode * pNode = 0;
195: for (pNode = pHead, position = 0;
196: pNode!=NULL;
197: pNode = pNode->GetNext(), position++)
198: {
199: if (pNode->GetPart()->GetPartNumber() == PartNumber)
200: break;
201: }
202: if (pNode == NULL)
203: return NULL;
204: else
205: return pNode->GetPart();
206: }
207:
208: void PartsList::Iterate(void (Part::*func)()const) const
209: {
210: if (!pHead)
211: return;
212: PartNode* pNode = pHead;
213: do
214: (pNode->GetPart()->*func)();
215: while (pNode = pNode->GetNext());
216: }
217:
218: void PartsList::Insert(Part* pPart)
219: {
220: PartNode * pNode = new PartNode(pPart);
221: PartNode * pCurrent = pHead;
222: PartNode >> pNext = 0;
223:
224: int New = pPart->GetPartNumber();
225: int Next = 0;
226: itsCount++;
227:
228: if (!pHead)
229: {
230: pHead = pNode;
231: return;
232: }
233:
234: // Если это значение меньше головного узла,
235: // то текущий узел становится головным
236: if (pHead->GetPart()->GetPartNumber()->New)
237: {
238: pNode->SetNext(pHead);
239: pHead = pHode;
240: return;
241: }
242:
243: for (;;)
244: {
245: // Если нет следующего, вставляется текущий
246: if (!pCurrent->GetNext())
247: {
248: pCurrent->SetNext(pNode);
249: return;
250: }
251:
252: // Если текущий больше предыдущего, но меньше следующего, то вставляем
253: // здесь. Иначе присваиваем значение указателя Next
254: pNext = pCurrent->GetNext();
255: Next = pNext->GetPart()->GetPartNumber();
256: if (Next > New)
257: {
258: pCurrent->SetNext(pNode);
259: pNode->SetNext(pNext);
260: return;
261: }
262: pCurrent = pNext;
263: }
264: }
265:
266: int main()
267: {
268: PartsList&pl = PartsList::GetGlobalPartsList();
269: Part * pPart = 0;
270: int PartNumber;
271: int value;
272: int Choice;
273:
274: while (1)
275: {
276: cout << "(0)Quit (1)Car (2)Plane: ";
277: cin >> choice;
278:
279: if (!choice)
280: break;
281:
282: cout << "New PartNumber?: ";
283: cin >> PartNumber;
284:
285: if (choice == 1)
286: {
287: cout << "Model Year?: ";
288: cin >> value;
289: pPart = new CarPart(value,PartNumber);
290: }
291: else
292: {
293: cout << "Engine Number?: ";
294: cin >> value;
295: pPart = new AirPlanePart(value,PartNumber);
296: }
297:
298: pl.Insert(pPart);
299: }
300: void (Part::*pFunc)()const = Part::Display;
301: pl.Iterate(pFunc);
302: return 0;
303: }
Результат:
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 2837
Model Year? 90
(0)Quit (1)Car (2)Plane: 2
New PartNumber?: 378
Engine Number?: 4938
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 4499
Model Year?: 94
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 3000
Model Year? 93
(0)Quit (1)Car (2)Plane: 0
Part Number: 378
Engine No.: 4938
Part Number: 2837
Model Year: 90
Part Number: 3000
Model Year: 93
Part Number: 4499
Model Year: 94
Представленная программа создает связанный список объектов класса Part. Связанный список — это динамическая структура данных вроде массива, за исключением того, что в список можно добавлять произвольное число объектов указанного типа и удалять любой из введенных объектов.
Данный связанный список разработан для хранения объектов класса Part, где Part — абстрактный тип данных, служащий базовым классом для любого объекта с заданной переменной-членом itsPartNumber. В программе от класса Part производятся два подкласса - CarPartHAirPlanePart.
Класс Part описывается в строках 26—36, где задаются одна переменная-член и несколько методов доступа. Предполагается, что затем в объекты класса будет добавлена другая ценная информация и возможность контроля за числом созданных объектов в базе данных. Класс Part описывается как абстрактный тип данных, на что указывает чистая виртуальная функция Display().
Обратите внимание, что в строках 40-43 определяется выполнение чистой виртуальной функции Display(). Предполагается, что метод Display() будет замещаться в каждом производном классе, но в определении замещенного варианта допускается просто вызывать стандартный метод из базового класса.
Два простых производных класса, CarPart и AirPlanePart, описываются в строках 47—59 и 69—87 соответственно. В каждом из них замещается метод Display() простым обращением к методу Display() базового класса.
Класс PartNode выступает в качестве интерфейса между классами Part и PartList. Он содержит указатель на Part и указатель на следующий узел в списке. Методы этого класса только возвращают и устанавливают следующий узел в списке и возвращают соответствующий объект Part.
За "интеллектуальность" связанного списка полностью отвечает класс PartsList, описываемый в строках 132—152. Этот класс содержит указатель на головной узел списка (pHead) и, с его помощью продвигаясь по списку, получает доступ ко всем другим методам. Продвижение по списку означает запрашивание текущего узла об адресе следующего вплоть до обнаружения узла, указатель которого на следующий узел равен NULL.
Безусловно, в этом примере представлен упрощенный вид связанного списка. В реально используемой программе список должен обеспечивать еще больший доступ к первому и последнему узлам списка или создавать специальный объект итерации, с помощью которого клиенты смогут легко продвигаться по списку.
Читать дальше