Рейтинговые книги
Читем онлайн Освой самостоятельно С++ за 21 день. - Джесс Либерти

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 100 101 102 103 104 105 106 107 108 ... 170

25: void Part::Display() const

26: {

27:    cout << "nPart Number: ";

28:    cout << itsPartNumber << endl;

29: }

30:

31: // ************** Класс Car Part ************

32:

33: class CarPart : public Part

34: {

35:    public:

36:       CarPart():itsModelYear(94){ }

37:       CarPart(int year, int partNumber);

38:       virtual void Display() const

39:       {

40:          Part::Display();

41:          cout << "Model Year: ";

42:          cout << itsModelYear << endl;

43:       }

44:    private:

45:       int itsModelYear;

46: };

47:

48: CarPart::CarPart(int year, int partNumber):

49:    itsModelYear(year),

50:    Part(partNumber)

51: { }

52:

53:

54: // *********** Класс AirPlane Part ***********

55:

56: class AirPlanePart : public Part

57: {

58:    public:

59:       AirPlanePart():itsEngineNumber(1){ };

60:       AirPlanePart

61:          (int EngineNumber, int PartNumber);

62:       virtual void Display() const

63:       {

64:          Part::Display();

65:          cout << "Engine No.: ";

66:          cout << itsEngineNumber << endl;

67:       }

68:    private:

69:       int itsEngineNumber;

70: };

71:

72: AirPlanePart::AirPlanePart

73:    (int EngineNumber, int PartNumber):

74:    itsEngineNumber(EngineNumber),

75:    Part(PartNumber)

76: { }

77:

78: // **************** Класс Part Node ************

79: class PartNode

80: {

81:    public:

82:       friend class PartsList;

83:       PartNode (Part*);

84:       ~PartNode();

85:       void SetNext(PartNode * node)

86:          { itsNext = node; }

87:       PartNode * GetNext() const;

88:       Part * GetPart() const;

89:    private:

90:       Part *itsPart;

91:       PartNode * itsNext;

92: };

93:

94:

95: PartNode::PartNode(Part* pPart):

96:    itsPart(pPart),

97:    itsNext(0)

98: { }

99:

100: PartNode::~PartNode()

101: {

102:    delete itsPart;

103:    itsPart = 0;

104:    delete itsNext;

105:    itsNext = 0;

106: }

107:

108: // Возвращается NULL, если нет следующего узла PartNode

109: PartNode * PartNode::GetNext() const

110: {

111:    return itsNext;

112: }

113:

114: Part * PartNode::GetPart() const

115: {

116:    if (itsPart)

117:       return itsPart;

118:    else

119:       return NULL; //ошибка

120: }

121:

122:

123: // ************** Класс Part List

124: class PartsList

125: {

126:    public:

127:       PartsList();

128:       ~PartsList();

129:       // Необходимо, чтобы конструктор-копировщик и оператор соответствовали друг другу

130:       void Iterate(void (Part::*f)()const) const;

131:       Part* Find(int & position, int PartNumber) const;

132:       Part* GetFirst() const;

133:       void Insert(Part *);

134:       Part* operator[](int) const;

135:       int GetCount() const { return itsCount; }

136:       static PartsList& GetGlobalPartsList()

137:       {

138:          return GiobalPartsList;

139:       }

140:    private:

141:       PartNode * pHead;

142:       int itsCount;

143:       static PartsList GiobalPartsList;

144: };

145:

146: PartsList PartsList::GlobalPartsList;

147:

148: // Implementations for Lists...

149:

150: PartsList::PartsList();

151:    pHead(0),

152:    itsCount(0)

153: { }

154:

155: PartsList::~PartsList()

156: {

157:    delete pHead;

158: }

159:

160: Part* PartsList::GetFirst() const

161: {

162:    if (pHead)

163:       return pHead->itsPart;

164:    else

165:       return NULL; // ловушка ошибок

166: }

167:

168: Part * PartsList::operator[](int offSet) const

169: {

170:    PartNode* pNode = pHead;

171:

172:    if (!pHead)

173:       return NULL; // ловушка ошибок

174:

175:    if (offSet > itsCount)

176:       return NULL; // ошибка

177:

178:    for (int i=0;i<offSet; i++)

179:       pNode = pNode->itsNext;

180:

181:    return pNode->itsPart;

182: }

183:

184: Part* PartsList::Find(int & position, int PartNumber) const

185: {

186:    PartNode * pNode = 0;

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

188:       pNode!=NULL;

189:       pNode = pNode->itsNext, position++)

190:    {

191:       if (pNode->itsPart->GetPartNumber() == PartNumber)

192:          break;

193:    }

194:    if (pNode == NULL)

195:       return NULL;

196:    else

197:       return pNode->itsPart;

198: }

199:

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

201: {

202:    if (!pHead)

203:       return;

204:    PartNode* pNode = pHead;

205:    do

206:       (pNode->itsPart->*func)();

207:    while (pNode = pNode->itsNext);

208: }

209:

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

211: {

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

213:    PartNode * pCurrent = pHead;

214:    PartNode * pNext = 0;

215:

216:    int New = pPart->GetPartNumber();

217:    int Next = 0;

218:    itsCount++;

219:

220:    if (!pHead)

221:    {

222:       pHead = pNode;

223:       return;

224:    }

225:

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

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

228:    if (pHead->itsPart->GetPartNumber() > New)

229:    {

230:       pNode->itsNext = pHead;

231:       pHead = pNode;

232:       return;

233:    }

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

Анализ: В строке 82 класс PartsList объявляется другом класса PartNode. В данном случае объявление класса другом происходит в разделе public объявления класса PartNode, но так поступать вовсе не обязательно. Это объявление можно размещать в любом месте объявления класса, что не изменит его суть. В результате объявления класса как друга все закрытые методы и переменные-члены класса PartNode становятся доступными любой функции-члену класса PartsList.

В строке 160 были внесены изменения в вызове функции-члена GetFirst() с учетом появившихся новых возможностей. Теперь вместо возвращения pHead->GetPart эта функция может возвращать закрытую переменную-член pHead->itsPart. Аналогичным образом в функции Insert() можно написать pNode->itsNext = pHead вместо переменной-члена pHead->SetNext(pHead).

В данном случае внесенные изменения существенно не улучшили код программы, поэтому нет особых причин делать класс PartsList другом PartNode. В данном примере просто хотелось проиллюстрировать, как работает ключевое слово friend.

Объявление классов-друзей следует применять с осторожностью. Класс объявляется как друг какого-либо иного класса в том случае, когда два класса тесно взаимодействуют друг с другом и открытие доступа одного класса к данным и методам другого класса существенно упрощает код программы. Однако зачастую проще организовать взаимодействие между классами с помощью открытых методов доступа.

1 ... 100 101 102 103 104 105 106 107 108 ... 170
На этой странице вы можете бесплатно читать книгу Освой самостоятельно С++ за 21 день. - Джесс Либерти бесплатно.

Оставить комментарий