|
Программирование >> Дополнительные возможности наследования
330: { 331: pPart = new CarPart(value,ObjectNumber): 332: } 333: catch (OutOfMemory) 334: { 335: cout Not enough memory; Exiting... endl; 336; return 1; 337; } 338: } 339; else 340; { 341; cout Engine Number?; ; 342: cin value; 343; try 344; { 345; pPart = new AirPlanePart(value,ObjectNumber); 346; } 347; catch (OutOfMemory) 348; { 349; cout Not enough memory; Exiting... endl; 350; return 1; 351; } 352: } 353; try 354; { 355: thelist,Insert(pPart); 356: } 357; catch (NullNode) 358; { 359: cout The list is broken, and the node is null! endl; 360: return 1; 361; } 362; catch (EmptyList) 363: { 364: cout The list is empty! endl; 365; return 1; 366; } 367; } 368; try 369; { 370; for (int i = 0; 1 < theList.GetCountO; 1++ ) 371: cout *(theList[i]); 372; } 373: catch (NullNode) 374: { 375: cout The list is broken, and the node is null! endl; 376: return 1; 377; } 378: catch (EmptyList) 379; { 380; cout The list is empty! << endl; 381 382 383 384 385 386 387 388 389 return 1; catch (BoundsError) { cout << Tried to read beyond the end of the list! endl; return 1; return 0; } lTfJt* (O)Quit (1)Car (2)Plane: 1 New PartNumber?; 2837 Model Year? 90 (O)Quit (1)Car (2)Plane: 2 New PartNumber?; 378 Engine Number?; 4938 (O)Quit (1)Car (2)Plane; 1 New PartNumber?; 4499 Model Year? 94 (O)Quit (l)Car (2)Plane: 1 New PartNumber?; 3000 Model Year? 93 (O)Quit (1)Car (2)Plane; 0 Part Number: 378 Engine No. 4938 Part Number: 2837 Model Year: 90 Part Number: 3000 Model Year: 93 Part Number 4499 Model Year: 94 Итоговая профамма, основанная на материале за неделю 3, - это модификация профаммы, приведенной в обзорной главе по материалам за неделю 2. Изменения заключались в добавлении шаблона, обработке объекта ostream и исключительных ситуаций. Результаты работы обеих профамм идентичны. В сфоках 36-40 объявляется ряд классов исключений. В этой профамме используется несколько примитивная обработка исключительных ситуаций. Классы исключений не содержат никаких данных или методов, они служат флагами для перехвата блоками catch, которые выводят простые предупреждения, а затем вьшолняют выход. Более надежная программа могла бы передать эти исключения по ссылке, а затем извлечь контекст или другие данные из объектов исключения, чтобы попытаться исправить возникшую проблему. В строке 45 объявляется абстрактный класс Part, причем точно так же, как это было сделано в листинге, обобшаюшем материал за неделю 2. Единственное интересное изменение здесь - это использование оператора operator (), который не является членом класса (он объявляется в строках 70-74). Обратите внимание, что он не является ни членом класса запчастей Part, ни другом класса Part. Он просто принимает в качестве одного из своих параметров ссылку на класс Part. Возможно, вы бы хотели иметь замещенный оператор operator () для объектов классов CarPart и AirPlanePart с учетом различий в типах объектов. Но поскольку профамма передает указатель на объект базового класса Part, а не указатель на указатель производных классов CarPart и AirPlanePart, то выбор правильной версии функции пришлось бы основывать не на типе объекта, а на типе одного из парамефов функции. Это явление называется контравариантностью и не поддерживается в С++. Есть только два пути достижения полиморфизма в С++: использование полиморфизма функций и виртуальных функций. Полиморфизм функций здесь не будет работать, сигнатуры функций, принимающих ссылку на класс Part, одинаковы. Виртуальные функции также не будут здесь работать, поскольку оператор operator не является функцией-членом класса запчастей Part. Вы не можете сделать оператор operator<< функцией-членом класса Part, потому что в профамме потребуется выполнить следующий вызов: cout thePart Это означает, что фактически вызов относится к объекту cout.operator (Part&), а объект cout не имеет версии оператора operator , который принимает ссылку на класс запчастей Part! Чтобы обойти это офаничение, в приведенной выше профамме используется только один оператор operator , принимающий ссылку на класс Part. Затем вызывается метод DisplayO, который является виртуальной функцией-членом, в результате чего вызывается правильная версия этого метода. В строках 130-143 класс Node определяется как шаблон. Он ифает ту же роль, что и класс Node в профамме из обзора за неделю 2, но эта версия класса Node не связана с объектом класса Part. Это значит, что данный класс может создавать узел фактически для любого типа объекта. Обратите внимание: если вы попытаетесь получить объект из класса Node и окажется, что не существует никакого объекта, то такая ситуация рассматривается как исключительная и исключение генерируется в строке 175. В строках 182-183 определяется общий шаблон класса List. Этот класс может содержать узлы любых объектов, которые имеют уникальные идентификационные номера, кроме того, он сохраняет их отсортированными в порядке возрастания номеров. Каждая из функций списка проверяет ситуацию на исключительность и при необходимости генерирует соответствуюшие исключения. В строках 307-308 управляющая профамма создает список двух типов объектов класса Part, а затем печатает значения объектов в списке, используя стандартные потоки вывода. Если бы в языке С++ поддерживалась контравариантность, можно было бы вызывать замещенные функции, основываясь на типе объекта указателя, на который ссылается указатель базового класса. Профамма, представленная в листинге 3.2, демонстрирует суть контравариантности, но, к сожалению, ее нельзя будет скомпилировать в С++.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |