Предупреждение: ВНИМАНИЕ: Этот листинг не будет скомпилирован!
Листинг 3.2. Пример контравариантности
#include
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
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[]
Название или действие: Приведение типа
Оператор: casting
Категория: 4 (мультипликтивные)
Название или действие: Умножение, деление, деление по модулю
Оператор: * / %
Категория: 5 (аддитивные)
Название или действие: Бинарный плюс, бинарный минус
Оператор: + -
Категория: 6 (сдвига)
Название или действие: Вывода и ввода
Оператор: <<, >>
Категория: 7 (отношения)
Название или действие: Меньше, меньше или равно, больше, больше или равно
Оператор: <, <=, >, =>
Категория: 8 (равенства)
Название или действие: Равно, не равно
Оператор: ==, !=
Категория: 9
Название или действие: Побитовое И
Оператор: &
Категория: 10
Название или действие: Побитовое исключающее ИЛИ
Оператор: ^
Категория: 11
Название или действие: Побитовое ИЛИ
Оператор: |
Категория: 12
Название или действие: Логическое И
Оператор: &&
Категория: 13
Название или действие: Логическое ИЛИ
Оператор: ||
Категория: 14
Название или действие: Условный
Оператор: ?:
Категория: 15 (присваивания)
Название или действие: Простое присваивание
Оператор: =
Название или действие: Присваивание с умножением и делением
Оператор: *= /=
Название или действие: Присваивание с делением по модулю
Оператор: %=
Название или действие: Присваивание с суммой и разностью
Оператор: += -=
Название или действие: Присваивание со сдвигом
Оператор: <<= >>=
Название или действие: Присваивание с побитовым И, включающим ИЛИ и исключающим ИЛИ
Оператор: &= |= ^=
Читать дальше