Неперегружаемые операторы C++

Какие операторы нельзя перегружать в C++?


person MKaufmann    schedule 20.05.2010    source источник
comment
Я думаю, что поиск в Google даст вам решение. кстати, по какой именно причине вы задаете этот вопрос.   -  person ckv    schedule 20.05.2010
comment
Действительно, поиск в Google (и Википедии) дает ответы на многие вопросы, заданные здесь, но что с того? Если бы каждый всегда использовал какую-то другую поисковую систему, прежде чем прийти сюда, то это привело бы к окончательной гибели этого сайта.   -  person Christopher Barber    schedule 20.05.2010
comment
@viswanathan - Извините, я подумал, что это интересный вопрос. В следующий раз потрачу больше времени на поисковую систему, а не сюда.   -  person MKaufmann    schedule 20.05.2010
comment
@Christopher, но не лучше ли посмотреть предыдущую ветку или использовать Google, чтобы найти ответ на очевидный вопрос? Но при этом было бы верно, если бы вопрос был бы таким, какой оператор может быть перегружен в С++. Но больше нет в вопросе сделал его актуальным здесь.   -  person mawia    schedule 20.05.2010
comment
Очевидно, было бы лучше поискать ответы на этом сайте, прежде чем задавать вопрос, и нет никаких сомнений в том, что Google часто указывает вам лучшие ответы, чем вы можете получить здесь. Я просто указал, что если всегда сначала обращаться к Google, то здесь будет задано меньше вопросов и на них будет дан ответ, и этот сайт в конечном итоге станет неактуальным.   -  person Christopher Barber    schedule 20.05.2010


Ответы (7)


Из Википедии:

Operator Name                           Syntax
Bind pointer to member by reference     a.*b
Member                                  a.b
Scope resolution                        a::b
Size of                                 sizeof(a)
Ternary                                 a ? b : c
Type identification                     typeid(a)

person Jaap Weidemann    schedule 20.05.2010

Я почти уверен, что C++ FAQ Lite, вероятно, охватывает это. Сразу могу вспомнить тернарный оператор, оператор . и оператор разрешения области видимости (::). Подумав немного, поскольку оператор . не может быть перегружен, .*, вероятно, тоже не может быть перегружен.

Есть также некоторые операторы, которые можно, но почти никогда не следует перегружать, включая оператор запятой, &&, ||, каждый из которых обычно создает точку последовательности. && и || также только (обычно) оценивают правильный операнд, если это необходимо. Ни одна из этих характеристик не относится к перегруженному оператору.

Хотя для этого есть несколько причин, перегрузка унарного оператора & (адрес-оф) также часто является довольно плохой идеей. Адрес объекта в значительной степени приравнивается к его идентификатору, поэтому его перегрузка может сделать несколько других вещей относительно сложными.

Изменить: что касается оценки правильного операнда только в случае необходимости (он же «Оценка короткого замыкания»): рассмотрите что-то вроде x && y. Выражение может быть истинным только в том случае, если левый операнд истинен. Если левый операнд оценивается как false, то выражение также должно быть ложным, а C (и C++) гарантирует, что правый операнд не вообще будет оцениваться. Это удобно (например), если вы хотите сделать что-то вроде if (ptr != NULL && ptr->member /*...*/ ). В этом случае, если указатель в NULL, выполнение останавливается, и вы никогда не пытаетесь разыменовать указатель.

Та же основная идея верна и для ||, но наоборот. В этом случае, если левый операнд оценивается как true, то выражение в целом должно быть true, независимо от того, что будет оцениваться правым операндом, поэтому (опять же) C и C++ гарантируют, что в этом случае правый операнд не будет оценивается.

Однако при перегрузке этих операторов при вычислении выражения all всегда будут оцениваться оба операнда. Первое выражение попытается разыменовать указатель, даже если это нулевой указатель, поэтому поведение будет неопределенным.

person Jerry Coffin    schedule 20.05.2010
comment
+1. Вам не хватает ?: в первом абзаце, но остальные заставили меня проголосовать за вас. - person Gorpik; 20.05.2010
comment
@Gorpik:?: - тернарный оператор, поэтому он включен, просто под другим именем... - person Jerry Coffin; 20.05.2010
comment
@Jerry Coffin: Ой, боюсь, я только что просмотрел первый абзац и увидел только самих операторов. - person Gorpik; 20.05.2010
comment
@Matthieu: Если я не ошибаюсь, он перегружает двоичный &, а не унарный. OTOH, Boost::Assign действительно перегружает оператор запятой и заставляет его работать довольно разумно (в этом отношении я сделал то же самое, хотя и не так хорошо). Я не могу точно вспомнить, но Boost::Spirit, вероятно, перегружает пару, против которой я рекомендовал. - person Jerry Coffin; 20.05.2010
comment
&& и || также только (обычно) оценивает правильный операнд, если это необходимо. кто-нибудь может объяснить эту строку подробнее? Спасибо! - person mawia; 20.05.2010
comment
@Jerry: правильно, моя ошибка, это двоичный файл &. У меня есть тенденция быть более слабым для DSEL, поэтому я не буду винить Spirit :) Что касается Assign, я всегда обнаруживал, что operator()() может работать так же хорошо, как запятая с некоторым прокси-объектом в миксе. - person Matthieu M.; 20.05.2010
comment
@mawia: эти два оператора (при работе с логическими значениями) сначала оценивают первый член и только оценивают второй (т.е. вызывают функцию), если первого недостаточно. Классический пример — Object* p = /**/; if (p && p->isValid()). Если бы && оценивал 2 термина (левый и правый), то мы бы использовали нулевой указатель для вызова isValid, что привело бы к неопределенному поведению. Однако если вы перегружаете этот оператор, то при выборе перегруженного оператора будут оцениваться оба термина, что изменит семантику, которую он традиционно несет. - person Matthieu M.; 20.05.2010
comment
@Matthieu М, вы не можете перегружать операторы, применяемые к указателям, только те, которые относятся к определенным пользователем типам, поэтому ваше обоснование && будет применяться только к интеллектуальным указателям. - person Pete Kirkham; 21.06.2010

Из этой статьи о перегрузке операторов

Большинство может быть перегружено. Единственные операторы C, которые не могут быть . и ?: (и sizeof, который технически является оператором). C++ добавляет несколько собственных операторов, большинство из которых можно перегрузить, за исключением :: и .*.

so

  • .
  • ?:
  • ::
  • .*
person BCS    schedule 20.05.2010
comment
Как отмечает Фред Ларсон, если вы хотите быть разборчивым, sizeof и typeid также являются операторами. - person BCS; 20.05.2010

., .*, ?:, ::, sizeof и typeid. (из http://en.wikipedia.org/wiki/C%2B%2B_operators#Other_operators)

person Fred Larson    schedule 20.05.2010

Следующие операторы не могут быть перегружены в C++:

.                       example: object.member_function()
.*                      example: object_reference.*member_function_ptr();
::                      example: some_name_space::function()
?:                      example: z = y > z ? y : z     (ternary operator)
person AraK    schedule 20.05.2010

GIYF: http://www.google.com/search?q=What+operators+can+not+be+overloaded+in+c%2B%2B%3F

Первый результат:

http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.5

Большинство может быть перегружено. Единственные операторы C, которые не могут быть . и ?: (и sizeof, который технически является оператором). C++ добавляет несколько собственных операторов, большинство из которых можно перегрузить, за исключением :: и .*.

person Tyler McHenry    schedule 20.05.2010
comment
Я обнаружил, что с помощью оператора, перегружающего список С++, что вы использовали? - person BCS; 20.05.2010
comment
Я знал, что это было в C++ FAQ Lite, но я просто скопировал исходный вопрос в Google, и о чудо, первый результат! - person Tyler McHenry; 20.05.2010

Операторы ., :?, ::, .*, typeid и sizeof.

person Jacob    schedule 20.05.2010