¿Cuándo uso un punto, una flecha o dos puntos para referirme a los miembros de una clase en C ++?

Viniendo de otros lenguajes derivados de C (como Java o C #) a C ++, al principio es muy confuso que C ++ tenga tres maneras de referirse a los miembros de una clase: a::b , ab , y a->b . ¿Cuándo uso cuál de estos operadores?

(Nota: Esto debe ser una entrada a las preguntas frecuentes de C ++ de Stack Overflow . Si desea criticar la idea de proporcionar una pregunta frecuente en este formulario, entonces la publicación en meta que inició todo esto sería el lugar para hacerlo). esa pregunta se monitorea en la sala de chat de C ++ , donde la idea de las preguntas frecuentes comenzó en primer lugar, por lo que es muy probable que su respuesta sea leída por aquellos a quienes se les ocurrió la idea).

Los tres operadores distintos que utiliza C ++ para acceder a los miembros de una clase o clase objeto, es decir, el doble colon :: , el punto . , y la flecha -> , se usan para tres escenarios diferentes que siempre están bien definidos. Saber esto te permite saber mucho sobre a y b simplemente mirando a a::b , ab , o a->b , respectivamente, en cualquier código que mires.

  1. a::b solo se usa si b es un miembro de la clase (o espacio de nombres) a . Es decir, en este caso, a voluntad siempre será el nombre de una clase (o espacio de nombres).

  2. ab solo se usa si b es un miembro del objeto (o referencia a un objeto) a . Entonces, para ab , a siempre será un objeto real (o una referencia a un objeto) de una clase.

  3. a->b es, originalmente, una notación abreviada para (*a).b . Sin embargo, -> es el único de los operadores de acceso miembro que puede estar sobrecargado, entonces si a es un objeto de una clase que sobrecarga el operator-> (estos tipos comunes son punteros inteligentes e iteradores), entonces el significado es lo que el diseñador de clase implementado. Para concluir: con a->b , si a es un puntero, b será un miembro del objeto al que se refiere el puntero a. Sin embargo, si a es un objeto de una clase que sobrecarga este operador, se invoca el operador de función de operator->() sobrecargado operator->() .


La letra pequeña:

  • En C ++, los tipos declarados como class , struct o union se consideran “del tipo de clase”. Entonces lo anterior se refiere a los tres.
  • Las referencias son, semánticamente, alias de los objetos, por lo que debería haber agregado “o referencia a un puntero” al # 3 también. Sin embargo, pensé que esto sería más confuso que útil, ya que las referencias a punteros ( T*& ) casi nunca se usan.
  • Los operadores de punto y flecha se pueden usar para referirse a miembros de clase estáticos de un objeto, aunque no sean miembros del objeto. (¡Gracias a Oli por señalar esto!)

Sugerir una alternativa para el punto 3 de sbi

a->b solo se usa si a es un puntero. Es una forma abreviada de (*a).b , el miembro b del objeto que apunta a. C ++ tiene dos tipos de punteros, punteros “regulares” e inteligentes. Para punteros regulares como A* a , el comstackdor implementa -> . Para punteros inteligentes como std::shared_ptr a , -> es una función miembro de la clase shared_ptr .

Justificación: el público objective de esta pregunta frecuente no está escribiendo punteros inteligentes. No necesitan saber -> realmente se llama operator->() , o que es el único método de acceso a miembros que se puede sobrecargar.