When do I use a dot, arrow, or double colon to refer to members of a class in C++?
从其他的C派生语言(如Java或C语言)到C++,首先非常令人困惑的是C++有三种方法来引用一个类的成员:EDCOX1,0,EDCOX1,1,EDCX1,2。我什么时候使用这些运算符中的哪一个?
(注:这意味着是堆栈溢出的C++FAQ的一个条目。如果你想批评在这个表单中提供一个常见问题解答的想法,那么在meta上发布的开始所有这一切的地方就是这样做的地方。这个问题的答案是在C++聊天室中进行监控的,FAQ的想法一开始就出现了,所以你的答案很可能会被那些想出这个想法的人读到。
C++用来访问类或类对象的三个不同的操作符,即双冒号EDCOX1 OR 0,点EDCOX1 1,和箭头EDCOX1 2,用于三个不同的场景,它们总是定义良好的。知道了这一点,您就可以通过查看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->()。
小字体:
- 在C++中,被声明为EDCOX1(28)、struct或union的类型被认为是"类类型"。所以上面提到的三个。
- 从语义上讲,引用是对象的别名,所以我也应该在3中添加"或对指针的引用"。然而,我认为这会比有用更令人困惑,因为很少使用指针(T*&)。
- 点和箭头运算符可用于引用对象中的静态类成员,即使它们不是对象的成员。(多亏奥利指出了这一点!)
- 应该澄清的是,.和->也可以用于通过对象访问类静态,即使它们不是严格的"对象成员"。
- @奥利:的确如此。我已经把它添加到了小字体中,因为我认为它不常见,也不重要,不足以在正文中列出。
- 为了完整性,可能值得指出的是,operator*()也可以超载,并且没有任何东西会迫使超载与operator->()保持一致!(我没有投反对票,只是通过一长串的复制品来到这里)
- @ OliCharlesworth,你知道C++标准中规定了什么地方吗?
- @Juanchopanza:但是,通过超载operator*和使用.,您无法获得->的链接行为。只有operator->重载才能实现这一点。
建议SBI第3点的备选方案
只有当a是指针时,才使用a->b。它是(*a).b的简写,是a所指对象的b成员。C++有两种指针:"正则"和智能指针。对于像A* a这样的常规指针,编译器实现->。对于像std::shared_ptr a这样的智能指针,->是shared_ptr类的成员函数。
理由:本常见问题解答的目标受众并非撰写智能指针。他们不需要知道->实际上被称为operator->(),或者它是唯一可以重载的成员访问方法。
- 不管我同意与否,我都给出一个+1,只是为了提供一个备选答案。
- 公平地说,EDCOX1(1)对于标准的迭代器来说也是超载的,任何C++程序员都很快就会遇到,所以说它只用于指针可能会让人困惑。
- KISCsiRKE"普通C++程序员"不需要编写智能指针或迭代器类型,只需使用它们即可。类似于指针的解引用"适用于两者。