Программирование >>  Дополнительные возможности наследования 

1 ... 231 232 233 [ 234 ] 235 236 237 ... 265


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, демонстрирует суть контравариантности, но, к сожалению, ее нельзя будет скомпилировать в С++.



1 ... 231 232 233 [ 234 ] 235 236 237 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика