从其他 C 派生语言(如 Java 或 C#)到 C++,C++ 具有三种引用类成员的方式一开始非常令人困惑:a::b
、a.b
和a->b
. 我什么时候使用这些运算符中的哪一个?
4 回答
C++ 用于访问类或类对象成员的三个不同的运算符,即双冒号::
、点.
和箭头->
,用于三种不同的场景,这些场景总是定义明确的。知道这一点后,您可以立即了解很多,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->
(常见的此类类型是智能指针和迭代器),那么含义就是类设计器实现的任何内容。总结: Witha->b
, ifa
是一个指针,b
将是指针a
所指对象的成员。但是,如果是重载此运算符的类的对象,则调用a
重载的运算符函数。operator->()
小字:
- 在 C++ 中,声明为
class
、struct
或union
的类型被视为“类类型”。所以上面提到的都是他们三个。 - 引用在语义上是对象的别名,所以我也应该在#3 中添加“或对指针的引用”。但是,我认为这会更令人困惑而不是有用,因为
T*&
很少使用对指针 ( ) 的引用。 - 点和箭头运算符可用于引用对象中的静态类成员,即使它们不是对象的成员。(感谢奥利指出这一点!)
Suggesting an alternative for sbi's point 3
a->b
is only used if a
is a pointer. It is a shorthand for (*a).b
, the b
member of the object that a
points 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
.
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.
点运算符用于直接成员选择场景。
print(a.b)
在这里,我们正在访问b
,它是对象的直接成员a
。因此,主要a
是一个对象,并且b
是a
.
箭头运算符用于间接成员选择场景。
print(a->b)
在这里,我们正在访问b
which 是对象的成员,它由 指向a
。它是简写,(*a).b
所以在这里,a
主要是指向对象的指针,并且b
是该对象的成员。
双冒号(Scope)运算符用于命名空间相关的直接成员选择场景。
print(a::b)
在这里,我们访问b
的是 class/namespace 的成员a
。所以,主要a
是 class/namespace 并且b
是 的成员(函数/变量等)a
。
#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
->
::
.
->