Джесс Либерти - Освой самостоятельно С++ за 21 день.
Подведение итогов
В приведенной ниже программе используются многие "продвинутые" методы, с которыми вы познакомились на протяжении трех недель усердных занятий. Программа содержит связанный список, основанный на шаблоне; кроме того, в ней проводится обработка исключительных ситуаций. Тщательно разберитесь в этой программе, и, если полностью ее поймете, значит, вы — программист C++.
Предупреждение:Если ваш компилятор не поддерживает шаблоны или блоки try и catch, вы не сможете скомпилировать эту программу.
Листинг 3.1. Программа, основанная на материалах недели 3
1: // ************************************
2: //
3: // Название: Обзор недели 3
4: //
5: // Файл: Week3
6: //
7: // Описание: Программа с использованием связанного списка
8: // на основе шаблона с обработкой исключительных ситуаций
9: //
10: // Классы: PART - хранит номера запчастей и потенциально другую
11: // информацию о запчастях. Зто будет
12: // пример класса для хранения списка.
13: // Обратите внимание на использование
14: // оператора << для печати информации о запчасти
15: // на основе его типа и времени выполнения,
16: //
17: // Node - действует как узел в классе List
18: //
19: // List - список, основанный на шаблоне, который
20: // обеспечивает работу связанного списка
21: //
22: //
23: // Автор: Jesse Liberty (jl)
24: //
25: // Разработан: Pentium 200 Pro. 128MB RAM MVC 5.0
26: //
27: // Требования: Не зависит от платформы
28: //
29: // История создания: 9/94 - Первый выпуск (jl)
30: // 4/97 - Обновлено (jl)
31: // ************************************
32:
33: #include <iostream.h>
34:
35: // классы исключений
36: class Exception { };
37: class OutOfMemory : public Exception{ };
38: class NullNode : public Exception{ };
39: class EmptyList : public Exception { };
40: class BoundsError : public Exception { };
41:
42:
43: // **************** Part **************
44: // Абстрактный базовый класс запчастей
45: class Part
46: {
47: public:
48: Part():its0bjectNumber(1) { }
49: Part(int 0bjectNumber):its0bjectNumber(ObjectNumber){ }
50: virtual ~Part(){ };
51: int GetObjectNumber() const { return itsObjectNumber; }
52: virtual void Display() const =0; // функция будет замещена в производном классе
53:
54: private:
55: int itsObjectNumber;
56: };
57:
58: // выполнение чистой виртуальной функции, необходимой
59: // для связывания объектов производного класса
60: void Part::Display() const
61: {
62: cout << "nPart Number: " << itsObjectNumber << endl;
63: }
64:
65: // Этот оператор << будет вызываться для всех объектов запчастей.
66: // Его не нужно объявлять другом, поскольку он не обращается к закрытым данным.
67: // Он вызывает метод Display(), в результате чего реализуется полиморфизм классов.
68: // Было бы не плохо замещать функцию оператора для разных
69: // типов thePart, но C++ не поддерживает контравариантность
70: ostream& operator<<( ostream& theStream,Part& thePart)
71: {
72: thePart.Display(); // косвенная реализация полиморфизма оператора вывода!
73: return theStream;
74: }
75:
76: // **************** Car Part ************
77: class CarPart : public Part
78: {
79: public:
80: CarPart():itsModelYear(94){ }
81: CarPart(int year, int partNumber);
82: int GetModelYear() const { return itsModelYear; }
83: virtual void Display() const;
84: private:
85: int itsModelYear;
86: };
87:
88: CarPart::CarPart(int year, int partNumber):
89: itsModelYear(year),
90: Part(partNumber)
91: { }
92:
93: void CarPart::Display() const
94: {
95: Part::Display();
96: cout << "Model Year: " << itsModelYear << endl;
97: }
98:
99: // **************** AirPlane Part ************
100: class AirPlanePart : public Part
101: {
102: public:
103: AirPlanePart():itsEngineNumber(1){ } ;
104: AirPlanePart(int EngineNumber, int PartNumber);
105: virtual void Display() const;
106: int GetEngineNumber()const { return itsEngineNumber; }
107: private:
108: int itsEngineNumber;
109: };
110:
111: AirPlanePart::AirPlanePart(int EngineNumber, int PartNumber):
112: itsEngineNumber(EngineNumber),
113: Part(PartNumber)
114: { }
115:
116: void AirPlanePart::Display() const
117: {
118: Part::Display();
119: cout << "Engine No,: " << itsEngineNumber << endl;
120: }
121:
122: // Обьявление класса List
123: template <class T>
124: class List;
125:
126: // **************** Node ************
127: // Общий узел, который можно добавить к списку
128: // **********************************
129:
130: template <class T>
131: class Node
132: {
133: public:
134: friend class List<T>;
135: Node (T*);
136: ~Node();
137: void SetNext(Node * node) { itsNext = node; }
138: Node * GetNext() const;
139: T * GetObject() const;
140: private:
141: T* its0bject;
142: Node * itsNext;
143: };
144:
145: // Выполнение узла...
146:
147: template <class T>
148: Node<T>::Node(T* p0jbect):
149: itsObject(pOjbect),
150: itsNext(0)
151: { }
152:
153: template <class T>
154: Node<T>::~Node()
155: {
156: delete its0bject;
157: itsObject = 0;
158: delete itsNext;
159: itsNext = 0;
160: }
161:
162: // Возвращает значение NULL, если нет следующего узла
163: template <class T>
164: Node<T> * Node<T>::GetNext() const
165: {
166: return itsNext;
167: }
168:
169: template <class T>
170: T * Node<T>::GetObject() const
171: {
172: if (itsObject)
173: return itsObject;
174: else
175: throw NullNode();
176: }
177:
178: // **************** List ************
179: // Общий шаблон списка
180: // Работает с любым нумерованным объектом
181: // **********************************
182: template <olass T>
183: class List
184: {
185: public:
186: List();
187: ~List();
188:
189: T* Find(int & position, int 0bjectNumber) const;
190: T* GetFirst() const;
191: void Insert(T *);
192: T* operator[](int) const;
193: int GetCount() const { return itsCount; }
194: private:
195: Node<T> * pHead;
196: int itsCount;
197: };
198:
199: // Выполнение списка...
200: template <class T>
201: List<T>::List();
202: pHead(0),
203: itsCount(0)
204: { }
205:
206: template <class T>
207: List<T>::~List()
208: {
209: delete pHead;
210: }
211:
212: template <class T>
213: T* List<T>::GetFirst() const
214: {
215: if (pHead)
216: return pHead->itsObject;
217: else
218: throw EmptyList();
219: }
220:
221: template <class T>
222: T * List<T>::operator[](int offSet) const
223: {
224: Node<T>* pNode = pHead;
225:
226: if (!pHead)
227: throw EmptyList();
228:
229: if (offSet > itsCount)
230: throw BoundsError();
231:
232: for (int i=0;i<offSet; i++)
233: pNode = pNode->itsNext;
234:
235: return pNode->itsObject;
236: }
237:
238: // Находим данный обьект в списке на основе его идентификационного номера (id)
239: template <class T>
240: T* List<T>::Find(int & position, int 0bjectNumber) const
241: {
242: Node<T> * pNode = 0;
243: for (pNode = pHead, position = 0;
244: pNode!=NULL;
245: pNode = pNode->itsNext, position++)
246: {
247: if (pNode->itsObject->GetObjectNumber() == 0bjectNumber)
248: break;
249: }
250: if (pNode == NULL)
251: return NULL;
252: else
253: return pNode->itsObject;
254: }
255:
256: // добавляем в список, если номер объекта уникален
257: template <class T>
258: void List<T>::Insert(T* pObject)
259: {
260: Node<T> * pNode = new Node<T>(p0bject);
261: Node<T> * pCurrent = pHead;
262: Node<T> * pNext = 0;
263:
264: int New = p0bject->Get0bjectNumber();
265: int Next = 0;
266: itsCount++;
267:
268: if (!pHead)
269: {
270: pHead = pNode;
271: return;
272: }
273:
274: // если номер текущего объекта меньше номера головного,
275: // то этот объект становится новым головным узлом
276: if (pHead->itsObject->GetObjectNumber() > New)
277: {
278: pNode->itsNext = pHead;
279: pHead = pNode;
280: return;
281: }
282:
283: for (;;)
284: {
285: // если нет следующего обьекта, добавляем в конец текущий объект
286: if (!pCurrent->itsNext)
287: {
288: pCurrent->itsNext = pNode;
289: return;
290: }
291:
292: // если данный объект больше текущего, но меньше следующего,
293: // то вставляем его между ними, в противном случае переходим к следующему объекту
294: pNext = pCurrent->itsNext;
295: Next = pNext->itsObject->GetObjectNumber();
296: if (Next > New)
297: {
298: pCurrent->itsNext = pNode;
299: pNode->itsNext = pNext;
300: return;
301: }
302: pCurrent = pNext;
303: }
304: }
305:
306:
307: int main()
308: {
309: List<Part> theList;
310: int choice;
311: int ObjectNumber;
312: int value;
313: Part * pPart;
314: while (1)
315: {
316: cout << "(0)Quit (1)Car (2)Plane: ";
317: cin >> choice;
318:
319: if (!choice)