Джесс Либерти - Освой самостоятельно С++ за 21 день.
- Название:Освой самостоятельно С++ за 21 день.
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джесс Либерти - Освой самостоятельно С++ за 21 день. краткое содержание
В книге широко представлены возможности новейшей версии программного продукта Microsoft Visual C++. Подробно описаны средства и подходы программирования современных профессиональных приложений. Материалы книги дополнены многочисленными демонстрационными программами, в процессе разработки которых максимально используются возможности программных инструментов Microsoft Visual Studio. Особое внимание уделено новинкам версии 6.0 и новейшим технологиям объектно-ориентированного программирования, включая использование библиотеки MFC и шаблонов классов, а также создание связанных списков. Отдельное занятие посвящено вопросам объектно-ориентированного анализа и проектирования приложений. Подробно рассмотрены все средства и подходы конструирования собственных пользовательских классов.
Книга рассчитана на широкий круг читателей, интересующихся современными проблемами программирования.
Освой самостоятельно С++ за 21 день. - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
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
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.
Объявление классов-друзей следует применять с осторожностью. Класс объявляется как друг какого-либо иного класса в том случае, когда два класса тесно взаимодействуют друг с другом и открытие доступа одного класса к данным и методам другого класса существенно упрощает код программы. Однако зачастую проще организовать взаимодействие между классами с помощью открытых методов доступа.
Примечание: От начинающих программистов C++ часто можно услышать замечание, что объявление классов-друзей противоречит принципу инкапсуляции, лежащему в основе объектно-ориентированного программирования. Это, честно говоря, довольно широко распространенная бессмыслица. Объявление класса-друга просто расширяет интерфейс другого класса, что влияет на инкапсуляцию не больше, чем открытое наследование классов.
Дружественный класс
Объявление одного класса другом какого-либо иного с помощью ключевого слова friend в объявлении второго класса открывает первому классу доступ к членам второго класса. Иными словами, я могу объявить вас своим другом, но вы не можете объявить себя моим другом. Пример:
class PartNode{
public:
friend class PartsList: // обьявление класса PartsList другом PartNode
Функции друзья
Иногда бывает необходимо предоставить права доступа не всему классу, а только одной или нескольким функциям-членам. Это реализуется посредством объявления друзьями функций-членов другого класса. Причем объявлять другом весь класс вовсе не обязательно. Фактически другом можно объявить любую функцию, независимо от того, является ли она функцией-членом другого класса или нет.
Функции друзья и перегрузка оператора
Интервал:
Закладка: