Материалы книги получены с http://www.itlibitum.ru/
Множественная передача
Самый распространенный пример гомоморфной иерархии - набор классов, соответствующих различным видам чисел: целым, комплексным, вещественным и т.д. Класс-предок такой иерархии может называться Number и иметь интерфейс следующего вида:
class Number {
public:
virtual Number operator+(const Number&) = 0;
virtual Number operator-(const Number&) = 0;
// И т.д.
};
class Integer : public Number {
private:
int i;
public:
Integer(int x) : i(x) {}
virtual Number operator+(const Number&);
// И т.д.
};
На бумаге все выглядит проще, чем в действительности. Как реализовать Integer::operator+(Number&), если нам не известно, что в скобках находится вовсе не Number, а некоторый производный класс? Для каждой пары типов, участвующих в сложении, существует свой алгоритм. Суммирование Complex + Integer отличается от Integer + Real, которое, в свою очередь, отличается от Integer + ArbitraryPrecisionNumber. Как программе разобраться, какой из алгоритмов следует использовать? Что-что? Кто сказал: «Запросить у аргумента оператора + его настоящий тип»? Немедленно встаньте в угол.
class Number {
protected:
int type; // Хранит информацию о настоящем типе
int TypeOf() { return type; }
// И т.д.
};
// Где-то в программе
switch (type) {
case kInteger: ...
case kComplex: ...
}
Именно этого знания типов мы постараемся избежать. Кроме того, все прямые реализации подобных схем не отличаются особой элегантностью. Вы когда-нибудь видели код, генерируемый компилятором для конструкции switch/case? Ни красоты, ни эффективности. Вместо этого мы объединим знания компилятора о типах с чудесами современной технологии - v-таблицами.
Назад Содержание Далее
|