16

Посмотрите на эти функции подписи:Почему оператор приращения postfix принимает фиктивный параметр?

class Number { 
public: 
    Number& operator++(); // prefix ++ 
    Number operator++ (int); // postfix ++ 
}; 

Приставка не принимает какого-либо параметра, но постфикс делает. Зачем? Я думал, что мы можем распознать их с разными типами возврата.

+0

* Только время * Перегрузка C++ по типу возвращаемого значения для оператора типа. –

+0

@Mike: Я не считаю, что в этом случае вступает в действие разрешение перегрузки. –

+0

Хорошая точка. Я всегда думал об этом как о «перегрузке оператора типа», но, возможно, есть лучший термин. –

ответ

8

Вы можете предоставить оператор ++ любой тип возврата, который вам нравится, поэтому нет способа отличить постфикс и префикс от этого. Поэтому компилятору нужен какой-то ключ.

Ото, я не знаю, почему это не могло не было сделано только в синтаксисе:

//prefix 
int& ++operator(); 
//postfix 
int& operator++(); 

В конце концов, имитируя использование в объявлениях имеет традиции в C и C++.

P.S. Другие плакаты: Это не имеет никакого отношения к перегрузке по типу возврата. postfix и prefix ++/- это два разных имени. Нет необходимости разрешать перегрузку в x++ или ++x, потому что совершенно ясно, какое название предназначено.

+0

, возможно, они могли бы сделать это так, как вы предложили :) .. так что просто для дифференциации компилятора они пишут параметр справа? другой Вопрос, почему они сделали postfix для принятия параметра, почему бы не префикс? они могли бы изменить взаимозаменяемость, какую-либо конкретную разницу? – Naruto

+0

Это, вероятно, потребовало бы особых льгот в грамматике, которая уже настолько сложна, насколько они приходят. Кроме того, следующим логическим шагом было бы превращение других унарных операторов в соответствие с префиксом/постфиксацией для согласованности. В этом случае, что означал бы «T & operator()»? –

+2

@Shadow: дополнительный параметр для постфикса работает как визуальное напоминание о том, что действие происходит с правой стороны. –

2

Вам не разрешается перегружать функции только с помощью возвращаемого типа, поэтому для разграничения между двумя одинаково выглядящими операторами operator++() необходим параметр фиктивного типа.

7

Префикс и постфикс ++ - это разные операторы. Со стандартным объявлением стиля Foo operator symbol(Foo &) не было очевидного способа отличить эти два. Вместо того, чтобы придумывать какой-то новый синтаксис, такой как Foo symbol operator(Foo &), который превратил бы его в особый случай, в отличие от всех других операторов и, вероятно, немного боль, чтобы разобрать, разработчики языка хотели другое решение.

Решение, которое они выбрали, было несколько странным. Они отметили, что все остальные операторы postfix (т. Е. Операторы, которые произошли после одного из их операндов) были фактически инфиксными операторами, которые принимали два аргумента. Например, простой старый + или -. Исходя из этого, разработчики языка решили, что наличие случайного фиктивного аргумента будет хорошим способом различать префикс и постфикс ++.

ИМХО, это одно из странных решений, принятых в качестве С ++. Но у вас это есть.

И вы не можете отличить их по типу возврата по двум причинам.

Во-первых, функции C++ не могут быть перегружены по типу возврата. У вас не может быть двух функций, которые имеют одинаковые имена и списки типов параметров, но разные возвращаемые значения.

Во-вторых, этот метод не был бы прочным или гибким, чтобы обрабатывать все возможные реализации префикса и постфикса ++.

Например, вам может понадобиться постфикс ++, который возвратил ссылочный тип, если единственная причина, по которой вы когда-либо вызывали его, заключалась в вызове побочного эффекта, не связанного со значением переменной, к которой вы его применяли. На мой взгляд, это будет очень плохая реализация, но C++ не о том, чтобы судить о том, какой тип глупого кода вы хотите написать, но о том, чтобы вы могли писать любой код, который, по вашему мнению, подходит для ситуации. И заставить вас использовать один тип стиля возврата для префикса ++ и постфикс ++ будет противоречить этому духу.

+3

Как примечание, я получил эту информацию от «Проекта и эволюции C++» Бьярне Строугруп. Я бы рекомендовал его, если вы действительно хотите понять, почему C++ - это так. Выращивание языка путем аккреции в среде, где обратная совместимость очень важна, приводит к множеству странных вещей. – Omnifarious

+0

Однако нет никаких хороших альтернатив. Вы могли бы придумать псевдооператор (например, 'operator +++'), который люди забудут или ошибаются, или добавят ключевое слово (например, 'post operator ++') или откажутся от использования самих операторов и вместо этого используют специальные имена (например, '__add__' и друзей Python). Все выглядят хуже, чем фиктивная переменная. –

+0

Да, 'operator post_increment' было бы намного легче читать, но затем' post_increment' становится зарезервированным словом, возможно разбивая компиляторы или другие программы, которые уже использовали это имя. Следовательно, «имена с наивысшими приоритетами двойного подчеркивания Python - это все зарезервированные» соглашения. См. Историю XHTML для примера того, почему бы не вызвать серьезную потерю совместимости в новом стандарте. –

6

Прямо из уст Бьярне в:

Это может быть как слишком мило и слишком тонким, но он работает, не требует нового синтаксиса, и имеет логику к безумию. Другие унарные операторы являются префиксами и не принимают аргументов, если они определены как функции-члены. Параметр «нечетный» и неиспользуемый фиктивный аргумент int используется для указания нечетных операторов постфикса. Другими словами, в постфиксном случае ++ находится между первым (реальным) операндом и вторым (фиктивным) аргументом и, таким образом, является постфиксным.

Эти объяснения необходимы, потому что механизм уникален и, следовательно, немного бородавки. Учитывая выбор, я бы, вероятно, ввел ключевые слова prefix и postfix, но в то время это казалось невозможным. Однако единственный важный момент в том, что механизм работает и может быть понят и использован немногими программистами, которые действительно нуждаются в нем.

Кстати, на мой взгляд, только префикс ++ должен быть Перегружаемые программистом, и постфикса ++ должен быть автоматически генерируется компилятором. Кто-нибудь согласен со мной?

+0

Кто-нибудь со мной согласен? - '#include ' – UncleBens

+0

Не то, как язык в настоящее время настроен, нет. Я думаю, что это было бы аккуратно, если бы после 0x мы могли бы использовать операторы по умолчанию и позволить компилятору строить их из других операторов, которые вы определяете. –

+0

http://www.stroustrup.com/dne.html –

0

Если бы у меня были мои барабанщики, постинкремент и многие операторы последовательности были разделены на две или три части; в случае постинкремента, утверждение типа «a = (b ++ + C++)»; было бы эффективно переведено как «a = postinc1 (b) + postinc1 (c); postinc2 (b); postinc2 (c);»; вторая часть пост-приращения будет пустой функцией. В реальной реализации вызовы postinc2() должны часто возникать, в то время как некоторые другие результаты сидят в стеке оценки; это не должно быть слишком сложно для компилятора для реализации.

В случае «& &» или «||» первая часть оператора будет работать только с левым операндом; если он возвратил ненулевое значение (для & &) или ненулевое значение (для ||), то вторая часть будет работать на оба операнда.

В случае «?»/«:» Первая часть оператора будет работать только с первым операндом. Если он возвращает ненулевое значение, вторая часть будет работать с первым и вторым параметрами; в противном случае третья часть будет работать на первом и третьем параметрах.

Есть ли что-нибудь в этом мире? Кажется странным, что C++ позволяет операторам переопределяться способами, которые нарушают поведение последовательности, но не позволяют их переопределять способами, которые его сохраняют.

0

Компилятор использует аргумент int для различения операторов префикса и постфикса. Для неявных вызовов значение по умолчанию равно нулю, поэтому actully не имеет столь большого разброса в функциональности перегруженного оператора ...

Смежные вопросы