it-swarm-ru.tech

Когда я использую точку, стрелку или двойное двоеточие для ссылки на члены класса в C ++?

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

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

231
sbi

Три различных оператора, которые использует 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*&) ) редко используются.
  • Операторы точка и стрелка могут использоваться для ссылки на статические члены класса из объекта, даже если они не являются членами объекта. (Спасибо Оли за указание на это!)
231
sbi

Предлагая альтернативу для пункта 3 sbi

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

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

33
MSalters