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

Resuelto sbi asked hace 13 años • 0 respuestas

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

_(Nota: esto pretende ser una entrada a las [Preguntas frecuentes sobre C++ de Stack Overflow](https://stackoverflow.com/questions/tagged/c++-faq). Si desea criticar la idea de proporcionar preguntas frecuentes en este formulario , entonces [la publicación en meta que inició todo esto](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag) sería el lugar para hacerlo Las respuestas a esa pregunta se monitorean en la [sala de chat de C++](https://chat.stackoverflow.com/rooms/10/c-lounge), donde comenzó la idea de las preguntas frecuentes, por lo que su respuesta es muy probable. para que lo lean aquellos a quienes se les ocurrió la idea.)_
sbi avatar Feb 13 '11 21:02 sbi
Aceptado

Los tres operadores distintos que C++ usa para acceder a los miembros de una clase u objeto de clase, a saber, los dos puntos dobles ::, el punto .y la flecha ->, se usan para tres escenarios diferentes que siempre están bien definidos. Saber esto le permite saber inmediatamente mucho sobre ay bcon solo mirar a::b, a.bo a->b, respectivamente, en cualquier código que mire.

  1. a::bsolo se usa si bes miembro de la clase (o espacio de nombres) a. Es decir, en este caso asiempre será el nombre de una clase (o espacio de nombres).

  2. a.bsolo se usa si bes un miembro del objeto (o una referencia a un objeto) a. Entonces a.b, for asiempre será un objeto real (o una referencia a un objeto) de una clase.

  3. a->bes, originalmente, una notación abreviada para (*a).b. Sin embargo, ->es el único de los operadores de acceso a miembros que se puede sobrecargar, por lo que si aes un objeto de una clase que se sobrecarga operator->(tales tipos comunes son punteros inteligentes e iteradores), entonces el significado es cualquiera que haya implementado el diseñador de clases. Para concluir: Con a->b, si aes un puntero, bserá miembro del objeto al que ahace referencia el puntero. Sin embargo, si aes un objeto de una clase que sobrecarga este operador, entonces operator->()se invoca la función del operador sobrecargado.


La letra pequeña:

  • En C++, los tipos declarados como class, structo unionse consideran "de tipo de clase". Entonces lo anterior se refiere a los tres.
  • Las referencias son, semánticamente, alias de objetos, por lo que debería haber agregado "o referencia a un puntero" al número 3 también. Sin embargo, pensé que esto sería más confuso que útil, ya que las referencias a punteros ( T*&) rara vez se utilizan.
  • Los operadores de punto y flecha se pueden utilizar para hacer referencia a miembros de clase estática de un objeto, aunque no sean miembros del objeto. (¡Gracias a Oli por señalar esto!)
sbi avatar Feb 13 '2011 14:02 sbi

Sugiriendo una alternativa para el punto 3 del OSE

a->bsolo se usa si aes un puntero. Es una abreviatura de (*a).b, el bmiembro del objeto aal que apunta. C++ tiene dos tipos de punteros, punteros "normales" e inteligentes. Para punteros regulares como A* a, el compilador implementa ->. Para punteros inteligentes como std::shared_ptr<A> a, ->es una función miembro de la clase shared_ptr.

Justificación: el público objetivo de estas preguntas frecuentes no escribe sugerencias inteligentes. No necesitan saber ->cómo se llama realmente operator->()o que es el único método de acceso de miembros que puede sobrecargarse.

MSalters avatar Feb 14 '2011 10:02 MSalters

El operador de punto se utiliza en escenarios de selección directa de miembros.

print(a.b)

Aquí estamos accediendo b, que es un miembro directo de un objeto a. Entonces, principalmente, aes un objeto y bes miembro (función/variable, etc.) de a.


El operador de flecha se utiliza en escenarios de selección de miembros indirectos.

print(a->b)

Aquí, estamos accediendo ba cuál es un miembro del objeto, al que apunta a. Es una abreviatura de (*a).by por lo tanto aquí, aes principalmente un puntero a un objeto y bes miembro de ese objeto.


El operador de dos puntos dobles (alcance) se utiliza en escenarios de selección directa de miembros relacionados con espacios de nombres.

print(a::b)

Aquí, estamos accediendo ba cuál es miembro de la clase/espacio de nombres a. Entonces, principalmente, aes una clase/espacio de nombres y bes miembro (función/variable, etc.) de a.

muditrustagii avatar Jan 24 '2020 06:01 muditrustagii
#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;
}

En el ejemplo de codificación anterior, vemos que:
* Acceder a miembros (atributos y funciones) desde una instancia (u objeto) usando el operador de punto ( .)
* Acceder a miembros (atributos y funciones) desde un puntero a un objeto (o creado por new) usando el operador de puntero ( ->)
* Accediendo a funciones miembro estáticas desde la clase misma sin tener un objeto como identificador usando dos puntos dobles ( ::). [ Nota: también puede invocar la función miembro estática desde una instancia con .o ->que no se recomienda]

Hu Xixi avatar Aug 16 '2019 14:08 Hu Xixi