从其他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!)