На третьем цикле пользователь вводит деталь для автомобиля под номером 4499 с годом выпуска 94. Происходит очередное приращение счетчика и сравнивается номер текущего объекта с объектом головного узла. В этот раз новый введенный идентификационный номер детали оказывается больше номера объекта, определяемого в pHead, поэтому запускается цикл for в строке 243.
Значение идентификационного номера головного узла равно 378. Второй узел содержит объект со значением 2837. Текущее значение — 4499. Исходно указатель pCurrent связывается с головным узлом. Поэтому при обращении к переменной next объекта, на который указывает pCurrent, возвращается адрес второго узла. Следовательно, условное выражение в строке 246 возвратит False.
Указатель pCurrent устанавливается на следующий узел, и цикл повторяется. Теперь проверка в строке 246 приводит к положительному результату. Если следующего элемента нет, то новый узел вставляется в конец списка.
На четвертом цикле вводится номер детали 3000. Дальнейшее выполнение программы напоминает предыдущий этап, однако в этом случае текущий узел имеет номер 2837, а значение следующего узла равно 4499. Проверка в строке 256 возвращает TRUE, и новый узел вставляется между двумя существующими.
Когда пользователь вводит 0, условное выражение в строке 279 возвращает TRUE и цикл while(1) прерывается. В строке 300 функция-член Display() присваивается указателю на функции-члены pFunc. В профессиональной программе присвоение должно проходить динамически, основываясь на выборе пользователем.
Указатель функции-члена передается методу Iterate класса PartsList. В строке 208 метод Iterate() проверяет, не является ли список пустым. Затем в строках 213—215 последовательно с помощью указателя функции-члена вызываются из списка все объекты Part. В итоге для объекта Part вызывается соответствующий вариант метода Display(), в результате чего для разных объектов выводится разная информация.
Итак, две недели изучения C++ уже позади. Сейчас вы наверняка свободно ориентируетесь в некоторых достаточно сложных аспектах объектно-ориентированного программирования, включая инкапсуляцию и полиморфизм.
Последняя неделя начинается с изучения дополнительных возможностей наследования. Затем на занятии 16 вы изучите потоки, а на занятии 17 познакомитесь с одним замечательным дополнением стандартов C++ — пространствами имен. Занятие 18 посвящено анализу основ объектно-ориентированного программирования. В этот день внимание будет сконцентрировано не столько на синтаксисе языка, сколько на изучении концепций объектно-ориентированного программирования. На занятии 19 вы познакомитесь с использованием шаблонов, а на занятии 20 узнаете о методах отслеживания исключительных ситуаций и ошибок. Наконец, на последнем занятии будут раскрыты некоторые хитрости и секреты программирования на C++, что сделает вас настоящим гуру в этой области.
День 15-й. Дополнительные возможности наследования
До настоящего момента вы использовали одиночное и множественное наследование для создания относительно простых связей между классами. Сегодня вы узнаете:
• Что такое вложение и как его использовать
• Что такое делегирование и как его использовать
• Как выполнить один класс внутри другого
• Как использовать закрытое наследование
Анализируя примеры, приведенные на предыдущих занятиях, вы, вероятно, заметили, что в классах допускается использование в переменных-членах объектов других классов. В этом случае программисты на C++ говорят, что внешний класс содержит внутренний. Так, класс Employee в качестве переменных-членов может содержать строковые объекты (с именем сотрудника) и объекты с целочисленными значениями (зарплатой и т.д.).
В листинге 15.1 представлен незавершенный, но весьма полезный класс String. Запуск такой программы не приведет к выводу каких-либо результатов, но она потребуется при написании других программ этого занятия.
Листинг 15.1. Класс string
1: #include
2: #include
3:
4: class String
5: {
6: public:
7: // конструкторы
8: String();
9: String(const char *const);
10: String(const String &)
11: ~String();
12:
13: // перегруженные операторы
14: char & operator[](int offset);
15: char operator[](int offset) const;
16: String operator+(const String&);
17: void operator+=(const String&);
18: String & operator= (const String &);
19:
20: // Общие методы доступа
21: int GetLen()const { return itsLen; }
22: const char * GetString() const { return itsString; }
Читать дальше