Освой самостоятельно С++ за 21 день.
Шрифт:
234:
235: for (;;)
236: {
237: // если нет следующего, вставляется текущий
238: if (!pCurrent->itsNext)
239: {
240: pCurrent->itsNext = pNode;
241: return;
242: }
243:
244: // если текущий больше предыдущего, но меньше следующего, то вставляем
245: // здесь. Иначе присваиваем значение указателя Next
246: pNext = pCurrent->itsNext;
247: Next = pNext->itsPart->GetPartNumber;
248: if (Next > New)
249: {
250: pCurrent->itsNext = pNode;
251: pNode->itsNext = pNext;
252: return;
253: }
254: pCurrent = pNext;
255: }
256: }
257:
258: class PartsCatalog : private PartsList
259: {
260: public:
261: void Insert(Part *);
262: int Exists(int PartNumber);
263: Part * Get(int PartNumber);
264: operator+(const PartsCatalog &);
265: void ShowAll { Iterate(Part::Display); }
266: private:
267: };
268:
269: void PartsCatalog::Insert(Part * newPart)
270: {
271: int partNumber = newPart->GetPartNumber;
272: int offset;
273:
274: if (!Find(offset, partNumber))
275: PartsList::Insert(newPart);
276: else
277: {
278: cout << partNumber << " was the ";
279: switch (offset)
280: {
281: case 0: cout << "first "; break;
282: case 1: cout << "second "; break;
283: case 2: cout << "third "; break;
284: default: cout << offset+1 << "th ";
285: }
286: cout << "entry. Rejected!\n";
287: }
288: }
289:
290: int PartsCatalog::Exists(int PartNumber)
291: {
292: int offset;
293: Find(offset,PartNumber);
294: return offset;
295: }
296:
297: Part * PartsCatalog::Get(int PartNumber)
298: {
299: int offset;
300: return (Find(offset, PartNumber));
301:
302: }
303:
304: int main
305: {
306: PartsCatalog pc;
307: Part * pPart = 0;
308: int PartNumber;
309: int value;
310: int choice;
311:
312: while (1)
313: {
314: cout << "(0)Quit (1)Car (2)Plane: ";
315: cin >> choice;
316:
317: if (!choice)
318: break;
319:
320: cout << "New PartNumber?: ";
321: cin >> PartNumber;
322:
323: if (choice == 1)
324: {
325: cout << "Model Year?: ";
326: cin >> value;
327: pPart = new CarPart(value,PartNumber);
328: }
329: else
330: {
331: cout << "Engine Number?: ";
332: cin >> value;
333: pPart = new AirPlanePart(value,PartNumber);
334: }
335: pc.Insert(pPart);
336: }
337: pc.ShowAll;
338: return 0;
339: }
Результат:
(0)Quit (1)Cat (2}Plane: 1
New PartNumber?: 1234
Model Year?: 94
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 4434
Model Year?: 93
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 1234
Model Year?: 94
1234 was the first entry. Rejected!
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 2345
Model Year?: 93
(0)Quit (1)Car (2)Plane: 0
Part Number: 1234
Model Year: 94
Part Number: 2345
Model Year: 93
Part Number: 4434
Model Year: 93
Анализ:
В строке 160 были внесены изменения в вызове функции-члена GetFirst с учетом появившихся новых возможностей. Теперь вместо возвращения pHead->GetPart эта функция может возвращать закрытую переменную-член pHead->itsPart. Аналогичным образом в функции Insert можно написать pNode->itsNext = pHead вместо переменной-члена pHead->SetNext(pHead).
В данном случае внесенные изменения существенно не улучшили код программы, поэтому нет особых причин делать класс PartsList другом PartNode. В данном примере просто хотелось проиллюстрировать, как работает ключевое слово friend.
Объявление классов-друзей следует применять с осторожностью. Класс объявляется как друг какого-либо иного класса в том случае, когда два класса тесно взаимодействуют друг с другом и открытие доступа одного класса к данным и методам другого класса существенно упрощает код программы. Однако зачастую проще организовать взаимодействие между классами с помощью открытых методов доступа.
Примечание:От начинающих программистов C++ часто можно услышать замечание, что объявление классов-друзей противоречит принципу инкапсуляции, лежащему в основе объектно-ориентированного программирования. Это, честно говоря, довольно широко распространенная бессмыслица. Объявление класса-друга просто расширяет интерфейс другого класса, что влияет на инкапсуляцию не больше, чем открытое наследование классов.