246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 75
Текст из файла (страница 75)
Функцию управления связанным списком оставим классуPartsList.Попробуем сначала решить эту задачу путем вложения одного класса в другой сделегированиемответственностиотклассаклассу,какпоказановлистинге15.5.Листинг15.5.ДелегированиеответственностиклассуPartsList,включенномувклассPartsCatalog1:#include<iostream.h>2:3://****************КлассPart************4:5://Абстрактныйбазовыйклассвсехдеталей6:classPart7:{8:public:9:Part():itsPartNumber(1){}10:Part(intPartNumber):11:itsPartNumber(PartNumber){}12:virtual~Part(){}13:intGetPartNumber()const14:{returnitsPartNumber;}15:virtualvoidDisplay()const=0;16:private:17:intitsPartNumber;18:};19:20://выполнениечистойвиртуальнойфункциив21://стандартномвидедлявсехпроизводныхклассов22:voidPart::Display()const23:{24:cout<<"\nPartNumber:"<<itsPartNumber<<endl;25:}26:27://************Автомобильныедетали**********28:29:classCarPart:publicPart30:{31:public:32:CarPart():itsModelYear(94){}33:CarPart(intyear,intpartNumber);34:virtualvoidDisplay()const35:{36:Part::Display();37:cout<<"ModelYear:";38:cout<<itsModelYear<<endl;39:}40:private:41:intitsModelYear;42:};43:44:CarPart::CarPart(intyear,intpartNumber):45:itsModelYear(year),46:Part(partNumber)47:{}48:49:50://*************Авиационныедетали************51:52:classAirPlanePart:publicPart53:{54:public:55:AirPlanePart():itsEngineNumber(1){}56:AirPlanePart57:(intEngineNumber,intPartNumber)58:virtualvoidDlsplay()const59:{60:Part::Display();61:cout<<"EngineNo.:";62:cout<<itsEngineNumber<<endl;63:}64:private:65:intitsEngineNumber;66:};67:68:AirPlanePart::AirPlanePart69:(intEngineNumber,intPartNumber):70:itsEngineNumber(EngineNumber),71:Part(PartNumber)72:{}73:74://***************Узлыспискадеталей**********75:classPartNode76:{77:public:78:PartNode(Part*);79:~PartNode();80:voidSetNext(PartNode*node)81:{itsNext=node;}82:PartNode*GetNext()const;83:Part*GetPart()const;84:private:85:Part*itsPart;86:PartNode*itsNext;87:};88://ВыполнениеPartNode...89:90:PartNode::PartNode(Part*pPart):91:itsPart(pPart),92:itsNext(0)93:{}94:95:PartNode::~PartNode()96:{97:deleteitsPart;98:itsPart=0;99:deleteitsNext;100:itsNext=0;101:}102:103://ВозвращаетсяNULL,еслинетследующегоузлаPartNode104:PartNode*PartNode::GetNext()const105:{106:returnitsNext;107:}108:109:Part*PartNode::GetPart()const110:{111:if(itsPart)112:returnitsPart;113:else114:returnNULL;//ошибка115:}116:117:118:119://****************Списокдеталей***********120:classPartsList121:{122:public:123:PartsList();124:~PartsList();125: // необходимо, чтобы конструктор-копировщик и оператор соответствовали другдругу!126:voidIterate(void(Part::*f)()const)const;127:Part*Find(int&position,intPartNumber)const;128:Part*GetFirst()const;129:voidInsert(Part*);130:Part*operator[](int)const;131:intGetCount()const{returnitsCount;}132:staticPartsList&GetGlobalPartsList()133:{134:returnGiobalPartsList;135:}136:private:137:PartNode*pHead;138:intitsCount;139:staticPartsListGiobalPartsList;140:};141:142:PartsListPartsList::GlobalPartsList;143:144:145:PartsList::PartsList():146:pHead(0),147:itsCount(0)148:{}149:150:PartsList::~PartsList()151:{152:deletepHead;153:}154:155:Part*PartsList::GetFirst()const156:{157:if(pHead)158:returnpHead->GetPart();159:else160:returnNULL;//ловушкаошибок161:}162:163:Part*PartsList::operator[](intoffSet)const164:{165:PartNode*pNode=pHead;166:167:if(!pHead)168:returnNULL;//ловушкаошибок169:170:if(offSet>itsCount)171:returnNULL;//ошибка172:173:for(inti=0;i<offSet;i++)174:pNode=pNode->GetNext();175:176:returnpNode->GetPart();177:}178:179:Part*PartsList::Find(180:int&position,181:intPartNumber)const182:{183:PartNode*pNode=0;184:for(pNode=pHead,position=0;185:pNode!=NULL;186:pNode=pNode->GetNext(),position++)187:{188:if(pNode->GetPart()->GetPartNumber()==PartNumber)189:break;190:}191:if(pNode==NULL)192:returnNULL;193:else194:returnpNode->GetPart();195:}196:197:voidPartsList::Iterate(void(Part::*func)()const)const198:{199:if(!pHead)200:return;201:PartNode*pNode=pHead;202:do203:(pNode->GetPart()->*func)();204:while(pNode=pNode->GetNext());205:}206:207:voidPartsList::Insert(Part*pPart)208:{209:PartNode*pNode=newPartNode(pPart);210:PartNode*pCurrent-pHead;211:PartNode*pNext=0;212:213:intNew=pPart->GetPartNumber();214:intNext=0;215:itsCount++;216:217:if(!pHead)218:{219:pHead=pNode;220:return;221:}222:223://еслиэтозначениеменьшеголовногоузла,224://тотекущийузелстановитсяголовным225:if(pHead->GetPart()->GetPartNumber()->New)226:{227:pNode->SetNext(pHead);228:pHead=pNode;229:return;230:}231:232:for(;;)233:{234://еслинетследующего,вставляетсятекущий235:if(!pCurrent->GetNext())236:{237:pCurrent->SetNext(pNode);238:return;239:}240:241://еслитекущийбольшепредыдущего,номеньшеследующего,товставляем242://здесь.ИначеприсваиваемзначениеуказателяNext243:pNext=pCurrent->GetNext();244:Next=pNext->GetPart()->GetPartNumber();245:if(Next>New)246:{247:pCurrent->SetNext(pNode);248:pNode->SetNext(pNext);249:return;250:}251:pCurrent=pNext;252:}253:}254:255:256:257:classPartsCatalog258:{259:public:260:voidInsert(Part*);261:intExists(intPartNumber);262:Part*Get(intPartNumber);263:operator+(constPartsCatalog&);264:voidShowAll(){thePartsList.Iterate(Part::Display);}265:private:266:PartsListthePartsList;267:};268:269:voidPartsCatalog::Insert(Part*newPart)270:{271:intpartNumber=newPart->GetPartNumber();272:intoffset;273:274:if(!thePartsList,Find(offset,partNumber))275:276:thePartsList.Insert(newPart);277:else278:{279:cout<<partNumber<<"был";280:switch(offset)281:{282:case0:cout<<"first";break;283:case1:cout<<"second";break;284:case2:cout<<"third";break;285:default;cout<<offset+1<<"th";286:}287:cout<<"entry.Rejected!\n";288:}289:}290:291:intPartsCatalog::Exists(intPartNumber)292:{293:intoffset;294:thePartsList.Find(offset,PartNumber);295:returnoffset;296:}297:298:Part*PartsCatalog::Get(intPartNumber)299:{300:intoffset;301:Part*thePart=thePartsList.Find(offset,PartNumber);302:returnthePart;303:}304:305:306:intmain()307:{308:PartsCatalogpc;309:Part*pPart=0;310:intPartNumber;311:intvalue;312:intchoice;313:314:while(1)315:{316:cout<<"(0)Quit(1)Car(2)Plane:";317:cin>>choice;318:319:if(!choice)320:break;321:322:cout<<"NewPartNumber?:";323:cin>>PartNumber;324:325:if(choice==1)326:{327:cout<<"ModelYear?:";328:cin>>value;329:pPart=newCarPart(value,PartNumber);330:}331:else332:{333:cout<<"EngineNumber?:";334:cin>>value;335:pPart=newAirPlanePart(value,PartNumber);335:}337:pc.Insart(pPart);338:}339:pc.ShowAli();340:return0;341:}Результат:(0)Qult(1)Car(2)Plane:1NewPartNumber?:1234ModelYear?:94(0)Quit(1)Car(2)Plane:1NewPartNumber?:4434ModelYear?:93(0)Quit(1)Car(2)Plane:1NewPartNumber?:1234ModelYear?:941234wasthefirstentry.Rejected!(0)Quit(1)Car(2)Plane:1NewPartNumber?:2345ModelYear?:93(0)Quit(1)Car(2)Plane:0PartNumber:1234ModelYear:94PartNumber:2345ModelYear:93PartNumber:4434ModelYear:93Примечание:Некоторыекомпиляторынесмогутоткомпилироватьстроку264,хотяонавполнесоответствуетстандартамC++.Есливашкомпиляторвозразитпротивзаписиэтойстроки,заменитееестрокой264:voidShowAll(){thePartsList.Iterate(&Part::Display):}(Обратите внимание на добавление амперсанта (знак &) перед Part:Display.) Если этосработает,свяжитесьсфирмой,поставившейвамэтоткомпилятор,ипоинтересуйтесь,гдеониего"откопали".Анализ:Влистинге15.5используютсяклассыPart,PartNodeиPartsList,скоторымивыужепознакомилисьприподведенииитоговвторойнедели.НовыйклассPartsCatalogобъявляетсявстроках257—267.ОниспользуетPartsListкаксвоюпеременную-член, которой делегирует управление списком.
Другими словами, классPartsCatalogвыполняетсясредствамиклассеPartsList.Обратите внимание, что клиенты класса PartsCatalog не имеет прямого доступа к классуPartsList.ИнтерфейсклассаPartsListреализуетсяметодамиклассаPartsCatalog,чтосущественноизменяетегоповедение.Например,методPartsCatalog::Insert()непозволяетдублироватьданные,вводимыевPartsList.ОпределениевыполненияфункцииPartsCatalog::Insert()начинаетсявстроке269.УобъектаPart,передаваемогокакпараметр,запрашиваетсязначениеегопеременной-членаitsPartNumber.ЭтозначениепередаетсяметодуFind()классаPartsList,иобъектдобавляетсявсписок,еслитольковспискененайдендругойобъектстакимженомером.Впротивномслучаевозвращаетсясообщениеобошибке.Обратитевнимание,чтовметодеInsert()классаPartCatologиспользуетсяпеременная-членэтогоклассаthePartList,являющаясяобъектомклассаPartList.Процедураподдержаниясвязногосписка и добавления объектов в него, а также поиска и возвращения данных из спискаполностью реализуется вложенным классом PartsList, объект которого является переменнойчленом класса PartsCatalog.