Проблемы с перегрузкой намного менее необычны, чем вы думаете. Не так давно у разработчиков STL не было перегруженного ->оператора для некоторых типов итераторов, поэтому приходилось использовать *.. Многие библиотеки определяют их непоследовательно. Действительно раздражает, когда вы работаете с шаблонами и не знаете точный тип.
Конрад Рудольф
1
вы также можете сделать a[0].bвместо (*a).b. Но это было бы не так правильно.
Sellorio
2
Мальчик, после многих лет программирования на C # возврат к C ++ не только утомителен, но и синтаксис C ++ уродлив и неприятен. После этого хочется принять душ. Программы, написанные на C и C ++, просто способствуют плохому программированию. Apple, до Unix, изо всех сил пыталась сделать язык таким же красивым, как Паскаль.
ATL_DEV 09
@ATL_DEV Я бы сказал, что многие уродливые вещи больше не считаются идиоматическими, но, к сожалению, это не значит, что вы можете позволить себе не знакомиться с ними как практикующий программист на C ++. Кроме того, синтаксически хороший путь часто не является семантически хорошим путем, но он также становится лучше, а не хуже. Но опять же, у меня Стокгольмский синдром C ++.
Тим Сегин
@TimSeguine Если вы когда-нибудь захотите увидеть красивый код, то посмотрите документацию внутри Macintosh. Думаю, они изобрели CamelCase. Очень наглядные имена переменных и элегантно отформатированный код. Им удалось сделать свой более поздний код на C почти таким же великолепным, как и их более ранний код на Паскале.
ATL_DEV 07
70
a->bобычно является синонимом (*a).b. Круглые скобки здесь необходимы из-за силы связывания операторов *и .: *a.bне будет работать, потому что .связывает сильнее и выполняется первым. Таким образом, это эквивалентно *(a.b).
Однако остерегайтесь перегрузки: поскольку оба ->и *могут быть перегружены, их значение может сильно различаться.
К binding strengthвы имеете в виду оператор приоритет? если нет, в чем разница между ними?
вишнупрасантх
1
@Vizkrig Да, эти два термина используются взаимозаменяемо (хотя «приоритет оператора», кажется, встречается гораздо чаще, по крайней мере, в последние годы).
Конрад Рудольф
45
В языке C ++ оператор стрелки ( ->) определяется как синоним разыменования указателя, а затем для .этого адреса используется оператор -оператор .
Например:
Если у вас есть объект anObject, и указатель aPointer:
Чтобы иметь возможность использовать один из методов объекта, вы разыменовываете указатель и вызываете метод по этому адресу:
(*aPointer).method();
Что можно было бы написать с помощью оператора стрелки:
aPointer->method();
Основная причина существования оператора стрелки заключается в том, что он сокращает типизацию очень распространенной задачи, а также позволяет легко забыть скобки вокруг разыменования указателя. Если вы забыли круглые скобки, оператор. -Оператор будет связывать сильнее, чем * -оператор, и заставит наш пример выполняться как:
*(aPointer.method());// Not our intention!
В некоторых других ответах также упоминается, что операторы C ++ могут быть перегружены и что это не так часто.
Технически пятнистость там уже не "оператор", или нет?
Мартин Ба
6
@Martin: большинство людей используют слово «оператор» для многих вещей, которые напрямую не используются для вычисления значений. Как для "::" ("оператор области видимости"). Я точно не знаю, какова точка зрения стандарта по этому поводу. В абстрактном смысле можно рассматривать «->» как функциональный оператор, отображающий последовательность типов (параметров) в тип возвращаемого значения, например, оператор haskell, который также записывается «->».
Йоханнес Шауб - лит
6
Я подчиняюсь! :-P
Мартин Ба
2
@ JohannesSchaub-litb: ::фактически является оператором, подобным .или ->, и в стандарте называется «оператором разрешения области видимости».
-> используется при доступе к данным, на которые у вас есть указатель.
Например, вы можете создать указатель ptr на переменную типа int intVar следующим образом:
int* prt =&intVar;
Затем вы можете использовать для него функцию, такую как foo, только путем разыменования этого указателя - чтобы вызвать функцию для переменной, на которую указывает указатель, а не для числового значения ячейки памяти этой переменной:
(*ptr).foo();
Без круглых скобок компилятор мог бы понять это как *(ptr.foo())из-за приоритета операторов, чего мы не хотим.
На самом деле это то же самое, что вводить
ptr->foo();
Как ->разыменование этого указателя и, таким образом, вызывает функцию foo()для переменной, на которую указывает указатель.
Точно так же мы можем использовать ->для доступа или установки члена класса:
->
оператора для некоторых типов итераторов, поэтому приходилось использовать*.
. Многие библиотеки определяют их непоследовательно. Действительно раздражает, когда вы работаете с шаблонами и не знаете точный тип.a[0].b
вместо(*a).b
. Но это было бы не так правильно.a->b
обычно является синонимом(*a).b
. Круглые скобки здесь необходимы из-за силы связывания операторов*
и.
:*a.b
не будет работать, потому что.
связывает сильнее и выполняется первым. Таким образом, это эквивалентно*(a.b)
.Однако остерегайтесь перегрузки: поскольку оба
->
и*
могут быть перегружены, их значение может сильно различаться.источник
binding strength
вы имеете в виду оператор приоритет? если нет, в чем разница между ними?В языке C ++ оператор стрелки (
->
) определяется как синоним разыменования указателя, а затем для.
этого адреса используется оператор -оператор .Например:
Если у вас есть объект
anObject
, и указательaPointer
:Чтобы иметь возможность использовать один из методов объекта, вы разыменовываете указатель и вызываете метод по этому адресу:
Что можно было бы написать с помощью оператора стрелки:
Основная причина существования оператора стрелки заключается в том, что он сокращает типизацию очень распространенной задачи, а также позволяет легко забыть скобки вокруг разыменования указателя. Если вы забыли круглые скобки, оператор. -Оператор будет связывать сильнее, чем * -оператор, и заставит наш пример выполняться как:
В некоторых других ответах также упоминается, что операторы C ++ могут быть перегружены и что это не так часто.
источник
new SomeClass()
возвращает указатель (SomeClass *
), а неSomeClass
объект. И вы начинаете с объявления,anObject
а потомaPointer
используетеp
.В C ++ 0x оператор получает второе значение, указывающее тип возвращаемого значения функции или лямбда-выражения.
источник
::
фактически является оператором, подобным.
или->
, и в стандарте называется «оператором разрешения области видимости».Чаще читаю справа налево и зову "в"
будет выглядеть так:
"baz в bar в foo становится квакером в qux"
источник
->
используется при доступе к данным, на которые у вас есть указатель.Например, вы можете создать указатель ptr на переменную типа int intVar следующим образом:
Затем вы можете использовать для него функцию, такую как foo, только путем разыменования этого указателя - чтобы вызвать функцию для переменной, на которую указывает указатель, а не для числового значения ячейки памяти этой переменной:
Без круглых скобок компилятор мог бы понять это как
*(ptr.foo())
из-за приоритета операторов, чего мы не хотим.На самом деле это то же самое, что вводить
Как
->
разыменование этого указателя и, таким образом, вызывает функциюfoo()
для переменной, на которую указывает указатель.Точно так же мы можем использовать
->
для доступа или установки члена класса:источник
Вы можете использовать -> для определения функции.
Это не лямбда. Это действительно функция. «->» указывает тип возвращаемого значения функции.
источник