Конструкторы вносят свою лепту в преобразование типов (см. п. п. 12.3.1 в [1]). Определение оператора stati c_cast<> фактически означает, что в классе Т должен быть задан конструктор инициализации с аргументом, тип которого совпадает.
Полиморфными называются классы с виртуальными функциями (см. главу 9).
с типом выражения е: выражение преобразуется конструктором в объект типа Т. Например, если мы еще раз взглянем на конструктор инициализации в классе ТМопеу, то увидим, что наш конструктор фактически выполняет неявное преобразование типа:
long double -> ТМопеу
Поэтому мы можем упростить интерфейс нашего класса ТМопеу за счет сокращения количества дружественных функций — нам нет необходимости писать три варианта операции сложения, достаточно написать один:
friend ТМопеу operator+(const ТМопеу &а, const ТМопеу &Ь);
Тем не менее правильно работают все три варианта сложения:
TMonet t = 2, s = 0;
s = t+t; cout << s << endl;
s = t+2; cout << s << endl;
s = 2+t; cout << s << endl;
Если мы опять включим отладочный вывод в наши конструкторы, то увидим, что сначала вызывается конструктор инициализации, аргументом которого является заданная константа, и только после этого срабатывает операция сложения. Точнее, в данном случае конструктор вызывается для создания временного анонимного объекта. С одной стороны, это позволяет нам не писать лишние функции, полагаясь на преобразования, с другой стороны, лишние вызовы конструктора, очевидно, снижают эффективность выполнения программы. Если же мы хотим повысить эффективность программы и избавиться от лишних вызовов конструкторов, то надо реализовать перегруженную операцию со всеми возможными сочетаниями параметров. Тогда в процессе работы просто будет вызываться подходящий вариант, и не будет выполняться никакой «закулисной» работы по преобразованию аргументов.
То же самое касается и методов: нам нет необходимости иметь два метода сложения с присваиванием. Достаточно оставить единственный — тот, параметром в котором является денежная сумма. При сложении денег с числом оно будет преобразовано в деньги конструктором. Таким образом, и операции сравнения нам достаточно реализовать в единственном экземпляре с двумя аргументами типа ТМопеу, как показано в листинге 3.13.
Листинг 3.13. Реализация функций друзей сравнения
bool operator==(const ТМопеу &а, const ТМопеу &Ь)
{ return (a.Summa == b.Summa); // сравниваются суммы
}
bool operator!=(const TMoney &a, const TMoney &b)
{ return !(a == b); // сравниваются деньги
}
bool operator<(const TMoney &a, const TMoney &b)
{ return (a.Summa < b.Summa); // сравниваются суммы
}
bool operator>=(con$t TMoney &a, const TMoney &b)
Листинг 3.13 (продолжение)
{ return !(а < b); // сравниваются деньги
}
bool operator>(const TMoney &а, const TMoney &b)
{ return !((a < b)&&(a == b)); // сравниваются деньги
}
bool operator<=(const TMoney &a, const TMoney &b)
{ return (a < b)||(a == b); // сравниваются деньги
}
Конструктор вызывается каждый раз, когда в операции с денежной суммой участвует константа-число. |