从其他C衍生语言(如Java或c#)到c++, c++有三种方法来引用类的成员,这一开始是非常令人困惑的:a::b, a.b和a->b。什么时候使用这些操作符中的哪一个?

_(Note: This is meant to be an entry to [Stack Overflow's C++ FAQ](https://stackoverflow.com/questions/tagged/c++-faq). If you want to critique the idea of providing an FAQ in this form, then [the posting on meta that started all this](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag) would be the place to do that. Answers to that question are monitored in the [C++ chatroom](https://chat.stackoverflow.com/rooms/10/c-lounge), 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.)_


当前回答

#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创建)的指针访问成员(属性和函数) *使用双冒号(::)从类本身访问静态成员函数,而没有对象作为句柄。[注意:你也可以从实例中调用静态成员函数。或->,不建议使用]

其他回答

c++用于访问类或类对象成员的三个不同操作符,即双冒号::、点和箭头->,用于三个始终定义良好的不同场景。知道了这一点,你就可以通过在你看到的任何代码中分别查看a::b, a.b或a->b,立即了解很多关于a和b的信息。

a::b is only used if b is a member of the class (or namespace) a. That is, in this case a will always be the name of a class (or namespace). a.b is only used if b is a member of the object (or reference to an object) a. So for a.b, a will always be an actual object (or a reference to an object) of a class. a->b is, originally, a shorthand notation for (*a).b. However, -> is the only of the member access operators that can be overloaded, so if a is 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 a is a pointer, b will be a member of the object the pointer a refers to. If, however, a is an object of a class that overloads this operator, then the overloaded operator function operator->() gets invoked.


细则:

In C++, types declared as class, struct, or union are 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!)

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

print(a.b)

这里,我们正在访问b,它是对象a的直接成员。因此,首先,a是一个对象,b是a的成员(函数/变量等)。


箭头操作符用于间接成员选择场景。

print(a->b)

这里,我们正在访问b,它是对象的一个成员,由a指向,它是(*a)的简写。这里,a主要是指向对象的指针,B是该对象的成员。


双冒号(作用域)操作符用于与名称空间相关的直接成员选择场景。

print(a::b)

这里,我们正在访问b,它是类/命名空间a的成员。因此,首先,a是类/命名空间,b是a的成员(函数/变量等)。

为sbi的第3点提出了替代方案

A ->b仅在A是指针时使用。它是(*a)的缩写。B, a指向的对象的B元素。c++有两种指针,“常规”指针和智能指针。对于像A* A这样的常规指针,编译器实现->。对于智能指针,例如std::shared_ptr<A> A, ->是类shared_ptr的成员函数。

基本原理:本FAQ的目标读者并不是在编写智能指针。他们不需要知道->实际上被称为operator->(),或者它是唯一可以重载的成员访问方法。

#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创建)的指针访问成员(属性和函数) *使用双冒号(::)从类本身访问静态成员函数,而没有对象作为句柄。[注意:你也可以从实例中调用静态成员函数。或->,不建议使用]