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

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

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

Ответ 1

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

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

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

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


Маленький шрифт:

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

Ответ 2

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

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

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

Ответ 3

#include <iostream>
#include <string>

using namespace std;

class Human {
private:
    int age;

public:
    string name;

    Human(int humanAge, string humanName) 
         : age(humanAge), name(std::move(humanName)) {}

    void DoSomething() {
        cout << age << endl;
    }

    static void DisplayAge(const Human& person) {
        cout << person.age << endl;
    }

    // ...
};

int main() {
    // Usage of Dot(.) 
    Human firstMan(13, "Jim"); // firstMan is an instance of class Human
    cout << firstMan.name << endl; // accessing member attributes
    firstMan.DoSomething(); // accessing member functions

    // Usage of Pointer Operator (->)
    Human* secondMan = new Human(24, "Tom");
    cout << secondMan->name << endl; // accessing member attributes
    secondMan->DoSomething(); // accessing member functions
    cout << (*secondMan).name << endl; // accessing member attributes
    (*secondMan).DoSomething(); // accessing member functions

    // Usage of Double Colon (::)
    Human::DisplayAge(firstMan);
    firstMan.DisplayAge(firstMan); // ok but not recommended
    secondMan->DisplayAge(firstMan); // ok but not recommended

    delete(secondMan);

    return 0;
}

Из приведенного выше примера кодирования мы видим, что:
* Доступ к членам (атрибутам и функциям) из экземпляра (или объекта) с помощью оператора точки (.)
* Доступ к элементам (атрибутам и функциям) из указателя на объект (или созданный new) с помощью оператора указателя (->)
* Доступ к статическим функциям-членам из самого класса без использования объекта в качестве дескриптора с использованием двойного двоеточия (::). [Примечание: вы также можете вызывать статическую функцию-член из экземпляра с . или ->, что не рекомендуется]