我何时使用点,箭头或双冒号来引用C中某个类的成员?

从其他C派生语言(如Java或C#)到C,最初非常令人困惑的是C有三种方式来引用类的成员: a::ba.ba->b . 我什么时候使用这些运营商中的哪一个?

(注意:这是Stack Overflow的C FAQ的一个条目 . 如果你想批评在这个表单中提供常见问题解答的想法,那么发布所有这些的meta上的帖子就是这样做的地方 . 这个问题在C聊天室中受到监控,其中FAQ的想法首先出现在那里,所以你的答案很可能被那些提出这个想法的人阅读 . )

回答(2)

3 years ago

三个不同的运算符C用于访问类或类对象的成员,即双冒号 :: ,点 . 和箭头 -> ,用于三个始终定义良好的不同场景 . 了解这一点,您可以通过分别查看 a::ba.ba->b ,立即了解 ab .

仅当 b 是类(或命名空间) a 的成员时,才使用

  • a::b . 也就是说,在这种情况下, a 将始终是类(或命名空间)的名称 .

  • a.b 仅在 b 是对象的成员(或对象的引用) a 时使用 . 因此,对于 a.ba 将始终是类的实际对象(或对象的引用) .

  • a->b 最初是 (*a).b 的简写符号 . 但是, -> 是唯一可以重载的成员访问运算符,因此如果 a 是一个重载 operator-> 的类的对象(常见的类型是智能指针和迭代器),那么意义就是类设计者实现的 . 总结:对于 a->b ,如果 a 是指针, b 将是指针 a 引用的对象的成员 . 但是,如果 a 是重载此运算符的类的对象,则会调用重载的运算符函数 operator->() .


小字:

  • 在C中,声明为class,struct或union的类型被视为“类类型” . 所以上面提到了所有这三个 .

  • 引用在语义上是对象的别名,所以我应该在#3中添加“或引用指针” . 但是,我认为这会比有用更令人困惑,因为很少使用对指针(T *&)的引用 .

  • 点和箭头运算符可用于引用对象中的静态类成员,即使它们不是对象的成员 . (感谢Oli指出这一点!)

3 years ago

建议替代sbi的第3点

仅当 a 是指针时才使用 a->b . 它是 (*a).b 的简写, a 指向的对象的 b 成员 . C有两种指针,"regular"和智能指针 . 对于常规指针,例如 A* a ,编译器实现 -> . 对于智能指针,例如 std::shared_ptr<A> a-> 是类 shared_ptr 的成员函数 .

理由:此常见问题解答的目标受众不是编写智能指针 . 他们不需要知道 - >真的称为operator - >(),或者它是唯一可以重载的成员访问方法 .