在 C++ 中,何时使用点、箭头或双冒号来引用类的成员?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4984600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:05:17  来源:igfitidea点击:

When do I use a dot, arrow, or double colon to refer to members of a class in C++?

c++c++-faq

提问by sbi

Coming from other C-derived languages (like Java or C#) to C++, it is at first very confusing that C++ has three ways to refer to members of a class: a::b, a.b, and a->b. When do I use which one of these operators?

从其他C来源的语言(如Java或C#)到C ++到来,这是起初很困惑的是C ++有三种方式来引用类的成员:a::ba.b,和a->b。我什么时候使用这些运算符中的哪一个?

(Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all thiswould be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)

(注意:这是Stack Overflow 的 C++ FAQ 的一个条目。如果你想批评以这种形式提供 FAQ 的想法,那么开始所有这一切的 meta 上的帖子将是这样做的地方。答案该问题在C++ 聊天室中受到监控,FAQ 的想法首先在这里开始,因此您的答案很可能会被提出该想法的人阅读。)

回答by sbi

The three distinct operators C++ uses to access the members of a class or class object, namely the double colon ::, the dot ., and the arrow ->, are used for three different scenarios that are always well-defined. Knowing this allows you to immediately know quite a lot about aand bjust by looking at a::b, a.b, or a->b, respectively, in any code you look at.

C++ 用来访问类或类对象的成员的三个不同的运算符,即双冒号::、点.和箭头->,用于始终定义明确的三种不同场景。认识到这一点,您可以立即知道了很多有关a,并b只要看一眼a::ba.ba->b分别,你看任何代码。

  1. a::bis only used if bis a member of the class (or namespace) a. That is, in this case awill always be the name of a class (or namespace).

  2. a.bis only used if bis a member of the object (or reference to an object) a. So for a.b, awill always be an actual object (or a reference to an object) of a class.

  3. a->bis, originally, a shorthand notation for (*a).b. However, ->is the only of the member access operators that can be overloaded, so if ais an object of a class that overloads operator->(common such types are smart pointers and iterators), then the meaning is whatever the class designer implemented. To conclude: With a->b, if ais a pointer, bwill be a member of the object the pointer arefers to. If, however, ais an object of a class that overloads this operator, then the overloaded operator function operator->()gets invoked.

  1. a::b仅当b是类(或命名空间)的成员时才使用a。也就是说,在这种情况下a将始终是类(或命名空间)的名称。

  2. a.b仅当b是对象的成员(或对对象的引用)时才使用a。因此,对于a.ba将始终是一个类的一个实际的对象(或对象的引用)。

  3. a->b最初是 的简写符号(*a).b。但是,->是唯一可以重载的成员访问运算符,因此如果a是重载的类的对象operator->(常见的此类类型是智能指针和迭代器),则其含义与类设计者实现的无关。总结: with a->b,如果a是指针,b将是指针a所指对象的成员。但是,如果a是重载此运算符的类的对象,则operator->()调用重载的运算符函数。



The small print:

小字:

  • In C++, types declared as class, struct, or unionare considered "of class type". So the above refers to all three of them.
  • References are, semantically, aliases to objects, so I should have added "or reference to a pointer" to the #3 as well. However, I thought this would be more confusing than helpful, since references to pointers (T*&) are rarely ever used.
  • The dot and arrow operators can be used to refer to static class members from an object, even though they are not members of the object. (Thanks to Oli for pointing this out!)
  • 在 C++ 中,声明为classstruct或 的类型union被视为“类类型”。所以以上是指他们三个。
  • 从语义上讲,引用是对象的别名,所以我也应该在 #3 中添加“或对指针的引用”。但是,我认为这会更令人困惑而不是有用,因为T*&很少使用对指针 ( ) 的引用。
  • 点和箭头运算符可用于从对象引用静态类成员,即使它们不是对象的成员。(感谢 Oli 指出这一点!)

回答by MSalters

Suggesting an alternative for sbi's point 3

为 sbi 的第 3 点建议替代方案

a->bis only used if ais a pointer. It is a shorthand for (*a).b, the bmember of the object that apoints to. C++ has two kinds of pointers, "regular" and smart pointers. For regular pointers such as A* a, the compiler implements ->. For smart pointers such as std::shared_ptr<A> a, ->is a member function of class shared_ptr.

a->b仅在a是指针时使用。它是一个速记(*a).b,所述b的对象,该对象的构件a点。C++ 有两种指针,“常规”指针和智能指针。对于诸如 之类的常规指针A* a,编译器实现->. 对于智能指针,例如std::shared_ptr<A> a->是类的成员函数shared_ptr

Rationale: the target audience of this FAQ isn't writing smart pointers. They don't need to know ->is really called operator->(), or that it is the only member access method that can be overloaded.

基本原理:此常见问题解答的目标受众不是编写智能指针。他们不需要知道->真的被调用operator->(),或者它是唯一可以重载的成员访问方法。

回答by Hu Xixi

#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;
}

From the coding example above, we see that:
* Accessing members(attributes and functions) from an instance(or object) using the dot operator (.)
* Accessing members(attributes and functions) from a pointer to an object(or created by new) using the pointer operator (->)
* Accessing static member functions from class itself without having an object as a handle using the double colon (::). [Note:you can also invoke the static member function from a instance with .or ->which is not recommended]

从上面的编码示例中,我们看到:
* 使用点运算符 ( .)从实例(或对象)
访问成员(属性和函数) * 从指向对象(或创建者new)的指针访问成员(属性和函数)使用指针运算符 ( ->)
* 从类本身访问静态成员函数,而无需使用双冒号 ( ::)作为句柄的对象。[注意:您也可以从实例中调用静态成员函数.->不推荐]

回答by muditrustagii

Dot operator is used in direct member selection scenarios.

点运算符用于直接成员选择场景。

print(a.b)

Here, we are accessing b, which is a direct member of an object a. So, primarily, ais an object and bis a member (function/ variable etc) of a.

在这里,我们正在访问b,它是对象的直接成员a。因此,主要a是一个对象,并且ba.



Arrow operator is used in indirect member selection scenarios.

箭头运算符用于间接成员选择场景。

print(a->b)

Here, we are accessing bwhich is a member of the object, that is pointed to by a. It is shorthand of (*a).band so here, ais primarily a pointer to an object and bis a member of that object.

在这里,我们访问的b是对象的成员,即由 指向a。它是(*a).band 所以在这里的简写,a主要是一个指向对象的指针,并且b是该对象的成员。



Double Colon (Scope) operator is used in namespace related direct member selection scenarios.

双冒号 (Scope) 运算符用于与命名空间相关的直接成员选择场景。

print(a::b)

Here, we are accessing bwhich is a member of the class/namespace a.So, primarily, ais a class/namespace and bis a member (function/ variable etc) of a.

在这里,我们正在访问bwhich 是类/命名空间的成员a。因此,主要a是类/命名空间,并且b是 的成员(函数/变量等)a