Я знаю, что могу использовать фиктивный int в операторе постфикса ++ в качестве someClassObject.operator ++ (5), но почему не могу использовать его как someClassObject ++ 5?
Потому что стандарт так говорит ™.
Из-за того, как код C ++ анализируется и компилируется, постфиксы ++
и --
работают немного по-другому.
Давайте посмотрим на стандарт C ++ 11 [черновик] .
13.5.1 Унарные операторы [over.unary]
[...] См. 13.5.7 для объяснения постфиксных унарных операторов ++
и --
.
Хорошо, поэтому ++
и --
считаются унарными операторами (т.е. принимает один операнд). Что-то вроде 1 ++ 2
подразумевает, что ++
является бинарным оператором (то есть принимает два операнда). Но здесь нет бинарного оператора ++
. Оператор postfix ++
должен быть перегружен как один, но на самом деле он не разрешается как единое целое. Давайте вернемся немного назад через стандарт.
13.3.1.2 Операторы в выражениях [over.match.oper]
Если любой из операндов имеет тип, который является классом или перечислением, может быть объявлена пользовательская операторная функция, которая реализует этот оператор † , или для преобразования операнда может потребоваться пользовательское преобразование к типу, который подходит для встроенного оператора. В этом случае разрешение перегрузки используется для определения, какую операторную функцию или встроенный оператор следует вызывать для реализации оператора . Поэтому запись оператора сначала преобразуется в эквивалентную запись вызова функции, как показано в таблице 11 (где @
обозначает один из операторов, охватываемых указанным подпунктом).
Table 11 — Relationship between operator and function call notation
Subclause | Expression | As member function | As non-member function
[...]
13.5.2 | a@b | (a).operator@(b) | operator@ (a, b)
[...]
13.5.7 | a@ | (a).operator@(0) | operator@ (a, 0)
(выделение добавлено)
† someClassObject
- это класс, и объявлена пользовательская операторная функция (test operator++(int x)
), поэтому данный конкретный пункт применим к вашему случаю.
Во-первых, я включил строку с подпунктом 13.5.2, чтобы устранить любые сомнения. §13.5.2 имеет дело с бинарными операторами. Но, как мы установили, в C ++ нет бинарного оператора ++
, а единственный постфиксный оператор ++
- унарный. Так что этот ряд не применяется.
Последний ряд более интересен. В соответствии с этим приращение постфикса будет «преобразовано», скажем, с obj++
до obj.operator++(0)
. Это означает, что int
уже пройдено из-за разрешения перегрузки.
Просто для полноты, вот §13.5.7:
13.5.7 [over.inc]
Определяемая пользователем функция с именем operator++
реализует оператор префикса и постфикса ++
. Если эта функция является функцией-членом без параметров или не-функцией с одним параметром класса или типа перечисления, она определяет оператор приращения префикса ++
для объектов этого типа. Если функция является функцией-членом с одним параметром (который должен иметь тип int
) или функцией, не являющейся членом, с двумя параметрами (второй из которых должен иметь тип int
), она определяет оператор приращения постфикса ++
для объектов этого типа. Когда приращение постфикса вызывается в результате использования оператора ++
, аргумент int
будет иметь значение ноль.
Я спрашиваю об этом, потому что operator+
можно использовать как someClassObject1 + someClassObject2
.
+
может быть как унарным, так и двоичным оператором. Вот почему +2
и 1 + 2
являются допустимыми выражениями. Но ++
- унарный оператор (даже если он перегружен как бинарный).