从其他C派生语言(如Java或C#)到C,最初非常令人困惑的是C有三种方式来引用类的成员: a::b , a.b 和 a->b . 我什么时候使用这些运营商中的哪一个?
a::b
a.b
a->b
(注意:这是Stack Overflow的C FAQ的一个条目 . 如果你想批评在这个表单中提供常见问题解答的想法,那么发布所有这些的meta上的帖子就是这样做的地方 . 这个问题在C聊天室中受到监控,其中FAQ的想法首先出现在那里,所以你的答案很可能被那些提出这个想法的人阅读 . )
三个不同的运算符C用于访问类或类对象的成员,即双冒号 :: ,点 . 和箭头 -> ,用于三个始终定义良好的不同场景 . 了解这一点,您可以通过分别查看 a::b , a.b 或 a->b ,立即了解 a 和 b .
::
.
->
a
b
仅当 b 是类(或命名空间) a 的成员时,才使用
a::b . 也就是说,在这种情况下, a 将始终是类(或命名空间)的名称 .
a.b 仅在 b 是对象的成员(或对象的引用) a 时使用 . 因此,对于 a.b , a 将始终是类的实际对象(或对象的引用) .
a->b 最初是 (*a).b 的简写符号 . 但是, -> 是唯一可以重载的成员访问运算符,因此如果 a 是一个重载 operator-> 的类的对象(常见的类型是智能指针和迭代器),那么意义就是类设计者实现的 . 总结:对于 a->b ,如果 a 是指针, b 将是指针 a 引用的对象的成员 . 但是,如果 a 是重载此运算符的类的对象,则会调用重载的运算符函数 operator->() .
(*a).b
operator->
operator->()
小字:
在C中,声明为class,struct或union的类型被视为“类类型” . 所以上面提到了所有这三个 .
引用在语义上是对象的别名,所以我应该在#3中添加“或引用指针” . 但是,我认为这会比有用更令人困惑,因为很少使用对指针(T *&)的引用 .
点和箭头运算符可用于引用对象中的静态类成员,即使它们不是对象的成员 . (感谢Oli指出这一点!)
建议替代sbi的第3点
仅当 a 是指针时才使用 a->b . 它是 (*a).b 的简写, a 指向的对象的 b 成员 . C有两种指针,"regular"和智能指针 . 对于常规指针,例如 A* a ,编译器实现 -> . 对于智能指针,例如 std::shared_ptr<A> a , -> 是类 shared_ptr 的成员函数 .
A* a
std::shared_ptr<A> a
shared_ptr
理由:此常见问题解答的目标受众不是编写智能指针 . 他们不需要知道 - >真的称为operator - >(),或者它是唯一可以重载的成员访问方法 .
2 回答
三个不同的运算符C用于访问类或类对象的成员,即双冒号
::
,点.
和箭头->
,用于三个始终定义良好的不同场景 . 了解这一点,您可以通过分别查看a::b
,a.b
或a->b
,立即了解a
和b
.仅当
b
是类(或命名空间)a
的成员时,才使用a::b
. 也就是说,在这种情况下,a
将始终是类(或命名空间)的名称 .a.b
仅在b
是对象的成员(或对象的引用)a
时使用 . 因此,对于a.b
,a
将始终是类的实际对象(或对象的引用) .a->b
最初是(*a).b
的简写符号 . 但是,->
是唯一可以重载的成员访问运算符,因此如果a
是一个重载operator->
的类的对象(常见的类型是智能指针和迭代器),那么意义就是类设计者实现的 . 总结:对于a->b
,如果a
是指针,b
将是指针a
引用的对象的成员 . 但是,如果a
是重载此运算符的类的对象,则会调用重载的运算符函数operator->()
.小字:
在C中,声明为class,struct或union的类型被视为“类类型” . 所以上面提到了所有这三个 .
引用在语义上是对象的别名,所以我应该在#3中添加“或引用指针” . 但是,我认为这会比有用更令人困惑,因为很少使用对指针(T *&)的引用 .
点和箭头运算符可用于引用对象中的静态类成员,即使它们不是对象的成员 . (感谢Oli指出这一点!)
建议替代sbi的第3点
仅当
a
是指针时才使用a->b
. 它是(*a).b
的简写,a
指向的对象的b
成员 . C有两种指针,"regular"和智能指针 . 对于常规指针,例如A* a
,编译器实现->
. 对于智能指针,例如std::shared_ptr<A> a
,->
是类shared_ptr
的成员函数 .理由:此常见问题解答的目标受众不是编写智能指针 . 他们不需要知道 - >真的称为operator - >(),或者它是唯一可以重载的成员访问方法 .