Выбрать главу

Обратите внимание: если вы попытаетесь получить объект из класса Node и окажется, что не существует никакого объекта, то такая ситуация рассматривается как исключительная и исключение генерируется в строке 175.

В строках 182—183 определяется общий шаблон класса List. Этот класс может содержать узлы любых объектов, которые имеют уникальные идентификационные номера, кроме того, он сохраняет их отсортированными в порядке возрастания номеров. Каждая из функций списка проверяет ситуацию на исключительность и при необходимости генерирует соответствующие исключения.

В строках 307—308 управляющая программа создает список двух типов объектов класса Part, а затем печатает значения объектов в списке, используя стандартные потоки вывода.

Если бы в языке C++ поддерживалась контравариантность, можно было бы вызывать замещенные функции, основываясь на типе объекта указателя, на который ссылается указатель базового класса. Программа, представленная в листинге 3.2, демонстрирует суть контравариантности, но, к сожалению, ее нельзя будет скомпилировать в C++.

Вопросы и ответы

В комментарии, содержащемся в строках 65-69 говорится, что C++ не поддерживает контравариантность. Что такое контравариантность?

Контравариантностью называется возможность создания указателя базового класса на указатель производного класс.

Предупреждение:ВНИМАНИЕ: Этот листинг не будет скомпилирован!

Листинг 3.2. Пример контравариантности

#include <iostream.h>

class Animal

{

   public:

      virtual void Speak() { cout << "Animal Speaks\n";}

};

class Dog : public Animal

{

   public:

      void Speak() { cout << "Dog Speaks\n"; }

};

class Cat : public Animal

{

   public:

      void Speak() { cout << "Cat Speaks\n"; }

};

void DoIt(Cat*);

void DoIt(Dog*);

int main()

{

   Animal * pA = new Dog;

   DoIt(pA);

   return 0;

}

void DoIt(Cat * с)

{

   cout << "They passed а cat!\n" << endl;

   c->Speak();

}

void DoIt(Dog * d)

{

   cout << "They passed a dog!\n" << endl;

   d->Speak();

}

Но в C++ эту проблему можно решить с помощью виртуальной функции.

#include<iostream.h>

class Animal

{

   public:

      virtual void Speak() { cout << "Animal Speaks\n"; }

};

class Dog : public Animal

{

   public:

      void Speak() { cout << "Dog Speaks\n"; }

};

class Cat : public Animal

{

   public:

      void Speak() { cout << "Cat Speaks\n"; }

};

void DoIt(Animal*);

int main()

{

   Animal * pA = new Dog;

   DoIt(pA);

   return 0;

}

void DoIt(Animal * с)

{

   cout << "They passed some kind of animal\n" << endl;

   c->Speak();

}

Приложение А

Приоритеты операторов 

 Важно понять, что операторы имеют приоритеты, но запоминать их совсем не обязательно.

Приоритет оператора определяет последовательность, в которой программа выполняет операторы в выражении или формуле. Если один оператор имеет приоритет над другим оператором, то он выполняется первым.

Приоритет оператора убывает с увеличением номера категории. Все операторы одной категории имеют равный приоритет. Унарные операторы (категория 3), условный оператор (категория 14) и операторы присваивания (категория 15) ассоциируются справа налево, все остальные — слева направо. В приведенной ниже таблице операторы перечислены по категориям в порядке убывания их приоритетности.

Категория: 1 (Наивысшего приоритета)

   Название или действие: Разрешение обасти видимости, индексирования

   Оператор: :: []

Категория: 2

   Название или действие: Прямое и косвенное обращение к члену класса

   Оператор: . ->

   Название или действие: Вызов функции

   Оператор: ()

   Название или действие: Постфиксные инкремент и декремент

   Оператор: ++ --

Ктегория: 3 (унарные)

   Название или действие: Префиксные инкремент и декремент

   Оператор: ++ --

   Название или действие: Размер

   Оператор: sizeof, sizeof()

   Название или действие: Дополнение до единицы и логическое отрицание

   Оператор: ^ !

   Название или действие: Унарные минус и плюс

   Оператор: - +

   Название или действие: Получение адреса и разыменование

   Оператор: ? *

   Название или действие: оздание и удаление динамического объекта

   Оператор: new, new[], delete, delete[]