Когда я использую точку, стрелку или двойное двоеточие для ссылки на члены класса в C ++? - PullRequest
232 голосов
/ 13 февраля 2011

Исходя из других производных от C языков (таких как Java или C #) и C ++, поначалу очень сбивает с толку, что в C ++ есть три способа обращения к членам класса: a::b, a.b и a->b , Когда я использую какой из этих операторов?

(Примечание: это должна быть запись в FAQ по C ++ в Stack Overflow . Если вы хотите критиковать идею предоставления FAQ в этой форме, тогда публикация на мета, которая началась все это было бы местом для этого. Ответы на этот вопрос отслеживаются в C ++ chatroom , где идея FAQ возникла в первую очередь, так что ваш ответ, скорее всего, будет прочитан теми, кто придумал эту идею.)

Ответы [ 2 ]

232 голосов
/ 13 февраля 2011

Три различных оператора C ++ используют для доступа к членам класса или объекта класса, а именно двойное двоеточие ::, точка . и стрелка ->, используются для трех различных сценариев, которые всегда хорошо определены. Знание этого позволяет сразу же узнать достаточно много о a и b, просто взглянув на a::b, a.b или a->b соответственно в любом коде, который вы просматриваете.

  1. a::b используется только в том случае, если b является членом класса (или пространства имен) a. То есть в этом случае a всегда будет именем класса (или пространства имен).

  2. a.b используется только в том случае, если b является членом объекта (или ссылкой на объект) a. Таким образом, для a.b, a всегда будет фактическим объектом (или ссылкой на объект) класса.

  3. a->b изначально является сокращенной записью для (*a).b. Тем не менее, -> является единственным оператором доступа к элементу, который может быть перегружен, поэтому, если a является объектом класса, который перегружает operator-> (обычно такие типы являются умными указателями и итераторами), то смысл любой реализован дизайнер классов. В заключение: с a->b, если a является указателем, b будет членом объекта, на который ссылается a. Однако если a является объектом класса, который перегружает этот оператор, то вызывается перегруженная операторная функция operator->().


Мелкий шрифт:

  • В C ++ типы, объявленные как class, struct или union, рассматриваются как "типа класса". Таким образом, вышесказанное относится ко всем трем из них.
  • Семантически ссылки - это псевдонимы объектов, поэтому мне следовало бы добавить "или ссылку на указатель" на # 3. Тем не менее, я подумал, что это будет более запутанным, чем полезным, поскольку ссылки на указатели (T*&) используются редко.
  • Операторы точки и стрелки могут использоваться для ссылки на статические члены класса из объекта, даже если они не являются членами объекта. (Спасибо Оли за то, что указал на это!)
34 голосов
/ 14 февраля 2011

Предложение альтернативы для точки sbi 3

a->b используется только в том случае, если a является указателем.Это сокращение для (*a).b, члена b объекта, на который указывает a.C ++ имеет два вида указателей: «обычные» и «умные» указатели.Для обычных указателей, таких как A* a, компилятор реализует ->.Для умных указателей, таких как std::shared_ptr<A> a, -> является функцией-членом класса shared_ptr.

Обоснование: целевая аудитория этого FAQ не пишет умные указатели.Им не нужно знать, что -> действительно называется operator->() или что это единственный метод доступа к элементу, который может быть перегружен.

...