Когда я использую точку, стрелку или двойную двоеточие, чтобы ссылаться на членов класса на С++?
Исходя из других 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
) с помощью оператора указателя (->
)
* Доступ к статическим функциям-членам из самого класса без использования объекта в качестве дескриптора с использованием двойного двоеточия (::
). [Примечание: вы также можете вызывать статическую функцию-член из экземпляра с .
или ->
, что не рекомендуется]