Первый случай суммирования использует перегруженную версию оператора + для суммирования двух значений типа SmallInt. Второй случай неоднозначен, поскольку 0 можно преобразовать в тип SmallInt и использовать версию оператора + класса SmallInt либо преобразовать объект s3 в тип int и использовать встроенный оператор суммы для типа int.
Упражнение 14.52. Какой из операторов operator+, если таковые вообще имеются, будет выбран для каждого из следующих выражений суммы? Перечислите функции-кандидаты, подходящие функции и преобразования типов для аргументов каждой подходящей функции:
struct LongDouble {
//
//
LongDouble operator+(const SmallInt&); //
};
LongDouble operator+(LongDouble&, double);
SmallInt si;
LongDouble ld;
ld = si + ld;
ld = ld + si;
Упражнение 14.53. С учетом определения класса SmallInt определите, допустимо ли следующее выражение суммы. Если да, то какой оператор суммы используется? В противном случае, как можно изменить код, чтобы сделать его допустимым?
SmallInt s1;
double d = s1 + 3.14;
Резюме
Перегруженный оператор должен либо быть членом класса, либо иметь по крайней мере один операнд типа класса. У перегруженных операторов должно быть то же количество операндов, порядок и приоритет, как у соответствующего оператора встроенного типа. Когда оператор определяется как член класса, его неявный указатель this связан с первым операндом. Операторы присвоения, индексирования, вызова функции и стрелки должны быть членами класса.
Объекты классов, которые перегружают оператор вызова функции, operator() называются "объектами функций". Такие объекты зачастую используются в комбинации со стандартными алгоритмами. Лямбда-выражения — это отличный способ определения простых классов объектов функции.
Класс может определить преобразования в или из своего типа, которые будут использованы автоматически. Неявные конструкторы, которые могут быть вызваны с одним аргументом, определяют преобразования из типа параметра в тип класса; операторы неявного преобразования определяют преобразования из типа класса в другие типы.
Термины
Объект функции (function object). Объект класса, в котором определен перегруженный оператор вызова. Объекты функций применяются там, где обычно ожидаются функции.
Оператор преобразования (conversion operator). Оператор преобразования — это функция-член, которая осуществляет преобразование из типа класса в другой тип. Операторы преобразования должны быть константными членами их класса. Такие функции не получают параметров и не имеют типа возвращаемого значения. Они возвращают значение типа оператора преобразования. То есть оператор operator int возвращает тип int, оператор operator string — тип string и т.д.
Перегруженный оператор (overloaded operator). Функция, переопределяющая значение одного из встроенных операторов. Функция перегруженного оператора имеет имя operator с последующим определяемым символом. У перегруженных операторов должен быть по крайней мере один операнд типа класса. У перегруженных операторов тот же приоритет, порядок и количество операндов, что и у их встроенных аналогов.
Пользовательское преобразование (user-defined conversion). Синоним термина преобразование типа класса.
Преобразование типа класса (class-type conversion). Преобразования в или из типа класса определяются конструкторами и операторами преобразования соответственно. Неявные конструкторы, получающие один аргумент, определяют преобразование из типа аргумента в тип класса. Операторы преобразования определяют преобразования из типа класса в заданный тип.
Сигнатура вызова (call signature). Представляет интерфейс вызываемого объекта. Сигнатура вызова включает тип возвращаемого значения и заключенный в круглые скобки разделяемый запятыми список типов аргументов.
Таблица функций (function table). Контейнер, как правило, карта или вектор, содержащий значения, позволяющие выбрать и выполнить функцию во время выполнения.
Шаблон функции (function template). Библиотечный шаблон, способный представить любой вызываемый тип.