从其他C派生语言(如Java或C#)到C ++,最初很困惑的是C ++有三种方式来引用类的成员:a::b
,a.b
,和a->b
。我什么时候使用这些运营商中的哪一个?
<子> (注意:这是Stack Overflow's C++ FAQ的一个条目。如果您想批评在此表单中提供常见问题解答的想法,那么the posting on meta that started all this就是这样做的地方。在C++ chatroom中监控了这个问题,首先是FAQ的想法,所以你的答案很可能会被那些提出想法的人阅读。) 子>
答案 0 :(得分:231)
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->
的类的对象(常见的类型是智能指针和迭代器)那么意义就是类设计师所实现的。总结:使用a->b
,如果a
是指针,b
将成为指针a
引用的对象的成员。但是,如果a
是重载此运算符的类的对象,则会调用重载的运算符函数operator->()
。
小字:
class
,struct
或union
的类型被视为“类类型”。所以上面提到了所有这三个。 T*&
)的引用。 答案 1 :(得分:33)
建议替代sbi的第3点
a->b
仅在a
是指针时使用。它是(*a).b
的简写,是b
指向的对象的a
成员。 C ++有两种指针,“常规”和智能指针。对于常规指针,例如A* a
,编译器实现->
。对于std::shared_ptr<A> a
等智能指针,->
是类shared_ptr
的成员函数。
理由:此常见问题解答的目标受众不是编写智能指针。他们不需要知道->
实际上被称为operator->()
,或者它是唯一可以重载的成员访问方法。
答案 2 :(得分:1)
在直接成员选择方案中使用点运算符。
High
在这里,我们正在访问profile_idc
,它是对象print(a.b)
的直接成员。因此,首先,b
是对象,a
是a
的成员(函数/变量等)。
箭头运算符用于间接成员选择方案中。
b
在这里,我们正在访问a
所指向的对象print(a->b)
。它是 b
的简写,因此在这里,a
主要是指向对象的指针,而(*a).b
是该对象的成员。
在与命名空间相关的直接成员选择方案中使用双冒号(范围)运算符。
a
在这里,我们正在访问b
,它是类/命名空间print(a::b)
的成员。因此,b
是一个类/命名空间,而a
是一个a
的成员(函数/变量等)。
答案 3 :(得分:-1)
#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
)从指向对象的指针(或由->
创建的对象)访问成员(属性和函数)
*使用双冒号(::
)从类本身访问静态成员函数,而无需将对象作为句柄。 [注意:,您还可以从.
或->
的实例中调用静态成员函数,不推荐使用]