Я понимаю , большинство перегрузки операторов, за исключением операторов доступа члена ->
, .*
, и ->*
т.д.
В частности, что передается этим операторным функциям, а что нужно возвращать?
Как операторная функция (например operator->(...)
) узнает, на какой член ссылается? Это может знать? Это вообще нужно знать?
Наконец, нужно ли учитывать какие-либо константы? Например, при перегрузке чего-то вроде operator[]
обычно вам потребуются как константная, так и неконстантная версия. Требуются ли для операторов доступа к членам константные и неконстантные версии?
const
и неconst
версииoperator->
не требуются , но предоставление обоих может быть полезным.->*
и.*
. Фактически, он даже не упоминает о них! Я считаю, что они редко попадают в FAQ, но я с удовольствием добавлю ссылку на этот вопрос из FAQ. Пожалуйста, не закрывайте это как обман FAQ!Ответы:
->
Это единственная действительно сложная задача. Это должна быть нестатическая функция-член, и она не принимает аргументов. Возвращаемое значение используется для поиска членов.
Если возвращаемое значение является другим объектом типа класса, а не указателем, то последующий поиск члена также обрабатывается
operator->
функцией. Это называется «детализированным поведением». Язык объединяетoperator->
вызовы в цепочку, пока последний из них не вернет указатель.->*
Этот сложен только в том, что в нем нет ничего особенного. Не перегруженный версия требует объект указателя на тип класса на левой стороне и объект указателя типа элемента справа. Но когда вы его перегружаете, вы можете принимать любые аргументы и возвращать все, что захотите. Это даже не обязательно должен быть нестатический член.
Другими словами, это один просто нормальный бинарный оператор , как
+
,-
, и/
. См. Также: Свободный оператор -> * перегружает зло?.*
и.
Их нельзя перегрузить. Когда левая часть относится к типу класса, уже есть встроенное значение. Возможно, имело бы смысл определить их для указателя с левой стороны, но комитет по разработке языков решил, что это скорее запутает, чем полезно.
Перегрузки
->
,->*
,.
и.*
может заполнить только в тех случаях , когда выражение будет определено, оно никогда не может изменить значение выражения , которое будет действительным, без перегрузки.источник
new
оператор, даже если он действителен, даже если он не перегружен.new
всегда перегружен, или правила перегрузки к нему на самом деле не применяются (13.5 / 5: функции выделения и освобождения, оператор new, operator new [], оператор delete и operator delete [], полностью описаны в 3.7 +0,4. атрибуты и ограничение , найденные в остальной части настоящего подпункта не распространяются на них , если явно не указаны в 3.7.4.) Но перегрузок унарных&
или бинарный файл&&
,||
или,
, или добавления перегрузокoperator=
или перегрузок просто о чем - нибудь для незаданного тип перечисления, может изменить значение выражения. Уточнил заявление, спасибо!Оператор -> особенный.
"Он имеет дополнительные, нетипичные ограничения: он должен возвращать объект (или ссылку на объект), который также имеет оператор разыменования указателя, или он должен возвращать указатель, который можно использовать для выбора того, на что указывает стрелка оператора разыменования указателя. " Брюс Экель: Thinking CPP Vol-one: operator->
Дополнительный функционал предоставлен для удобства, поэтому вам не нужно звонить
Вы можете просто сделать:
Это отличает оператор -> от других перегрузок оператора.
источник
Вы не можете перегрузить доступ к члену
.
(т.е. вторая часть того, что->
делает). Однако вы можете перегрузить унарный оператор разыменования*
(т.е. первую часть того, что->
выполняет).Оператор C ++
->
- это, по сути, объединение двух шагов, и это ясно, если вы думаете, чтоx->y
он эквивалентен(*x).y
. C ++ позволяет вам настроить, что делать с(*x)
деталью, когдаx
она является экземпляром вашего класса.Семантика
->
перегрузки несколько странная, потому что C ++ позволяет либо вернуть обычный указатель (который будет использоваться для поиска указанного объекта), либо вернуть экземпляр другого класса, если этот класс также предоставляет->
оператор. Когда во втором случае поиск разыменованного объекта продолжается с этого нового экземпляра.источник
->*
, поскольку это эквивалентно форме(*x).*
?->
Оператор не знает , что элемент на который указывает на, он просто предоставляет объект для выполнения фактического доступа участника на.Кроме того, я не вижу причин, по которым вы не можете предоставить версии с константой и неконстантой.
источник
Когда вы перегружаете оператор -> () (здесь аргументы не передаются), компилятор фактически вызывает -> рекурсивно, пока он не вернет фактический указатель на тип. Затем он использует правильный член / метод.
Это полезно, например, для создания класса интеллектуального указателя, который инкапсулирует фактический указатель. Вызывается перегруженный оператор->, делает все, что он делает (например, блокирует для обеспечения безопасности потоков), возвращает внутренний указатель, а затем компилятор вызывает -> для этого внутреннего указателя.
Что касается константности - на него ответили в комментариях и других ответах (вы можете и должны предоставить оба).
источник