Читаем Освой самостоятельно С++ за 21 день. полностью

174:    for (int i=0;i

175:       pNode = pNode->GetNext;

176:

177:    return pNode->GetPart;

178: }

179:

180: Part* PartsList::Find(

181:    int & position,

182:    int PartNumber) const

183: {

184:    PartNode * pNode = 0;

185:    for (pNode = pHead, position = 0;

186:       pNode!=NULL;

187:       pNode = pNode->GetNext, position++)

188:    {

189:       if (pNode->GetPart->GetPartNumber == PartNumber)

190:          break;

191:    }

192:    if (pNode == NULL)

193:       return NULL;

194:    else

195:       return pNode->GetPart;

196: }

197:

198: void PartsList::Iterate(void (Part::*func)const) const

199: {

200:    if (!pHead)

201:       return;

202:    PartNode* pNode = pHead;

203:    do

204:       (pNode->GetPart->*func);

205:    while (pNode = pNode->GetNext);

206: }

207:

208: void PartsList::Insert(Part* pPart)

209: {

210:    PartNode * pNode = new PartNode(pPart);

211:    PartNode * pCurrent = pHead;

212:    PartNode * pNext = 0;

213:

214:    int New = pPart->GetPartNumber;

215:    int Next = 0;

216:    itsCount++;

217:

218:    if (!pHead)

219:    {

220:       pHead = pNode;

221:       return;

222:    }

223:

224:    // если это значение меньше головного узла,

225:    // то текущий узел становится головным

226:    if (pHead->GetPart->GetPartNumber->New)

227:    {

228:       pNode->SetNext(pHead);

229:       pHead = pNode;

230:       return;

231:    }

232:

233:    for (;;)

234:    {

235:       // еcли нет следующего, вставляется текущий

236:       if (!pCurrent->GetNext)

237:       {

238:          pCurrent->SetNext(pNode);

239:          return;

240:       }

241:

242:       // если текущий больше предыдущего, но меньше следующего, то вставляем

243:       // здесь, Иначе присваиваем значение указателя Next

244:       pNext = pCurrent->GetNext;

245:       Next = pNext->GetPart->GetPartNumber;

246:       if (Next > New)

247:       {

248:          pCurrent->SetNext(pNode);

249:          pNode->SetNext(pNext);

250:          return;

251:       }

252:       pCurrent = pNext;

253:    }

254: }

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 = newAirPlanePart(value,PartNumber);

334:       }

335:       pc.Insert(pPart);

336:    }

337:    pc.ShowAll;

338: return 0;

339: }


Результат:

(0)Quit (1)Car (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


Анализ: В листинге 15.6 был изменен интерфейс класса PartsCatalog и переписана функция main. Интерфейсы других классов остались такими же, как и в листинге 15.5.

В строке 258 листинга 15.6 класс PartsCatalog производится как private от класса PartsList. Интерфейс класса PartsCatalog остался таким же, как и в листинге 15.5, хотя, конечно же, необходимость в объектах класса PartsList как переменных-членах отпала.

Функция-член ShowAll класса PartsCatalog вызывает функцию Iterate из PartsList, параметром которой задается указатель на функцию-член класса Part. Таким образом, функция ShowAll выполняет роль открытого интерфейса, позволяя пользователям получать информацию, не обращаясь напрямую к закрытой функции Iterate, прямой доступ к которой закрыт для клиентов класса PartsCatalog.

Функция Insertтоже изменилась. Обратите внимание, в строке 274 функция Find теперь вызывается непосредственно, поскольку она наследуется из базового класса. Чтобы при вызове функции Insert не возникло зацикливания функции на самое себя, в строке 275 делается явный вызов функции с указанием имени класса.

Таким образом, если методам класса PartsCatalog необходимо вызвать методы PartsList, они могут делать это напрямую. Единствейное исключение состоит в том, что при необходимости заместить метод базового класса в классе PartsList следует явно указать класс и имя функции.

Закрытое наследование позволяет PartsCatalog унаследовать функциональность базового класса и создавать интерфейс, косвенно открывающий доступ к его методам, которые нельзя вызывать напрямую.


Рекомендуется:Применяйте открытое наследование, когда производный класс является разновидностью базового. Используйте вложение классов, когда необходимо делегировать выполнение задач другому классу, ограничив при этом доступ к его защищенным членам. Применяйте закрытое наследование, если необходимо реализовать один класс в пределах другого и обеспечить доступ к защищенным членам базового класса.


Не рекомендуется:Не применяйте закрытое наследование, если необходимо использовать более одного объекта базового класса. Для этих целей больше подойдет вложение классов. Например, если для одного объекта PartsCatalog необходимы два объекта PartsList, вы не сможете использовать закрытое наследование. Не используйте открытое наследование, если необходимо закрыть клиентам производного класса прямой доступ к методам базового класса.


Перейти на страницу:

Похожие книги

Сущность технологии СОМ. Библиотека программиста
Сущность технологии СОМ. Библиотека программиста

В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.

Дональд Бокс

Программирование, программы, базы данных / Программирование / Книги по IT