98 votes

Quelle est la différence entre ": :" "." et "->" en c++.

J'ai créé une classe appelée Kwadrat . La classe a trois int champs. Mon Environnement de développement me suggère d'accéder aux champs de Kwadrat des objets créés via le :: & -> opérateurs. J'ai essayé les deux opérateurs, et j'ai constaté que le -> est en mesure d'accéder avec succès aux données des champs d'objets, mais il n'en va pas de même pour l'opérateur de l'UE. -> opérateur. J'ai également constaté que le . accédera également aux membres de la classe. Je suis confus et ne comprends pas pourquoi il y a trois membres pour accéder aux membres de l'objet et/ou aux méthodes. Quelqu'un peut-il m'expliquer quelle est la différence entre ces trois opérateurs ?


          1. ->

          2. ::

          3. .


    #include <iostream>

    using namespace std;

    class Kwadrat{

    public: 
        int val1,
            val2,
            val3;

        Kwadrat(int val1, int val2, int val3)
        {
            this->val1 = val1; // Working
            this.val2 = val2;  // Doesn't Work!
            this::val3 = val3; // Doesn't Work!
        }
    };

    int main()
    {
        Kwadrat* kwadrat = new Kwadrat(1,2,3);

        cout<<kwadrat->val1<<endl;
        cout<<kwadrat->val2<<endl;
        cout<<kwadrat->val3<<endl;

        return 0;
    }

1 votes

1 votes

@reopen-voters : d'habitude, je fustige les aveugles qui votent à la clôture, mais maintenant, cette question est vraiment est un duplicata . tout nouvel éclairage peut être ajouté à la question qu'il duplique.

179voto

Andrew Points 14301

1. -> pour accéder aux variables et méthodes des membres de l'objet via pointer à l'objet

Foo *foo = new Foo();
foo->member_var = 10;
foo->member_func();

2. . pour accéder aux variables et méthodes des membres de l'objet via l'objet instance

Foo foo;
foo.member_var = 10;
foo.member_func();

3. :: pour accéder aux variables statiques et aux méthodes d'un class/struct o namespace . Il peut également être utilisé pour accéder à des variables et des fonctions à partir d'une autre portée (en fait, les classes, les structures et les espaces de noms sont des portées dans ce cas).

int some_val = Foo::static_var;
Foo::static_method();
int max_int = std::numeric_limits<int>::max();

0 votes

@ltjax : Les références sont accessibles comme des variables normales. Vous pouvez faire ref = 2; o ref.x = 5; pour une instance d'objet.

1 votes

Je sais, je faisais juste une allusion au fait que tu pourrais vouloir l'ajouter à 2.

1 votes

Vous pouvez avoir une référence à n'importe lequel d'entre eux. Une référence garde toujours le même type. C'est en fait un sujet différent.

30voto

Heisenbug Points 20496

En C++, vous pouvez accéder aux champs ou aux méthodes en utilisant différents opérateurs, en fonction de leur type :

  • Nom de la classe::Nom du champ : classe champ et méthodes statiques publics
  • ClassInstance.FieldName : accès à un champ (ou une méthode) public par référence à une classe
  • ClassPointer->FieldName accès à un champ (ou une méthode) public déréférencement d'un pointeur de classe

Notez que : : doit être utilisé avec un nom de classe plutôt qu'avec une instance de classe, puisque les champs ou méthodes statiques sont communs à toutes les instances d'une classe.

class AClass{
public:
static int static_field;
int instance_field;

static void static_method();
void method();
};

alors vous accédez de cette façon :

AClass instance;
AClass *pointer = new AClass();

instance.instance_field; //access instance_field through a reference to AClass
instance.method();

pointer->instance_field; //access instance_field through a pointer to AClass
pointer->method();

AClass::static_field;  
AClass::static_method();

0 votes

Mais je ne peux pas obtenir l'accès par AClass::static_field = 0 ;

0 votes

J'aime le caractère unicode de votre commentaire, @Yoda :)

19voto

RageD Points 3219

En termes très simples :: est l'opérateur de cadrage, . est l'opérateur d'accès (j'ai oublié quel est son nom actuel ?), et -> est la flèche de déréférencement.

:: - Définit la portée d'une fonction. En d'autres termes, elle permet au compilateur de savoir dans quelle classe se trouve la fonction et, par conséquent, comment l'appeler. Si vous utilisez cet opérateur pour appeler une fonction, cette dernière est une fonction de type static fonction.

. - Cela permet d'accéder à une fonction membre sur un objet déjà créé. Par exemple, Foo x; x.bar() appelle la méthode bar() sur l'objet instancié x qui a le type Foo . Vous pouvez également l'utiliser pour accéder aux variables publiques des classes.

-> - Essentiellement la même chose que . sauf que cela fonctionne sur les types de pointeurs. En fait, il déréférence le pointeur, puis appelle . . Cette utilisation est équivalente à (*ptr).method()

8voto

Jerry Coffin Points 237758

Vous avez un pointeur sur un objet. Par conséquent, vous devez accéder à un champ d'un objet qui est pointé par le pointeur. Pour déréférencer le pointeur, vous utilisez * et pour accéder à un champ, vous utilisez . pour que vous puissiez l'utiliser :

cout << (*kwadrat).val1;

Notez que les parenthèses sont nécessaires. Cette opération est suffisamment courante pour qu'il y a longtemps (à l'époque où le C était jeune), on ait décidé de créer une méthode "sténographique" pour la réaliser :

cout << kwadrat->val1;

Ils sont définis comme étant identiques. Comme vous pouvez le constater, le -> combine simplement une * y un . en une seule opération. Si vous traitiez directement un objet ou une référence à un objet, vous pourriez utiliser la fonction . sans déréférencer un pointeur au préalable :

Kwadrat kwadrat2(2,3,4);

cout << kwadrat2.val1;

Le site :: est l'opérateur de résolution de la portée. Il est utilisé lorsque vous avez seulement besoin de qualifier l'élément nom mais vous n'avez pas du tout affaire à un objet individuel. Il s'agit principalement d'accéder à un membre de données statique :

struct something { 
    static int x; // this only declares `something::x`. Often found in a header
};

int something::x;  // this defines `something::x`. Usually in .cpp/.cc/.C file.

Dans ce cas, puisque x est static il n'est pas associé à un cas particulier de something . En fait, il existera même si aucune instance de ce type d'objet n'a été créée. Dans ce cas, nous pouvons y accéder avec l'opérateur de résolution de portée :

something::x = 10;

std::cout << something::x;

Notez toutefois qu'il est également permis d'accéder à un membre statique comme s'il s'agissait d'un membre d'un objet particulier :

something s;

s.x = 1;

Du moins, si ma mémoire est bonne, au début de l'histoire du C++, cela n'était pas autorisé, mais la signification est sans ambiguïté, alors ils ont décidé de l'autoriser.

0 votes

Vous m'avez beaucoup aidé mais je ne comprends pas pourquoi cela ne fonctionne pas class Something{ public : static int i ; } ; Something::i = 0 ; cout<<Something::i<<endl ;

1 votes

@RobertKilar : Qui déclare mais ne fait pas définir Something::i; Vous avez donc besoin d'une définition séparée, par exemple int Something::i; comme je le montre dans l'exemple de code dans la réponse. Sinon, le code sera compilé mais ne sera pas lié, parce que Something::i sera une "référence externe non résolue/non définie".

7voto

Platinum Azure Points 22380

Les trois opérateurs ont des significations connexes mais différentes, malgré la note trompeuse de l'IDE.

Le site :: est connu comme l'opérateur opérateur de résolution de la portée Il est utilisé pour passer d'un espace de nom ou d'une classe à l'un de ses membres.

Le site . y -> permettent d'accéder aux membres d'une instance d'objet, et n'entrent en jeu qu'après la création d'une instance d'objet. Vous utilisez . si vous avez un objet réel (ou une référence à l'objet, déclarée à l'aide de la commande & dans le type déclaré), et vous utilisez -> si vous avez un pointeur vers un objet (déclaré avec * dans le type déclaré).

Le site this est toujours un pointeur vers l'instance courante, d'où la raison pour laquelle l'objet -> L'opérateur est le seul qui fonctionne.

Exemples :

// In a header file
namespace Namespace {
    class Class {
        private:
            int x;
        public:
            Class() : x(4) {}
            void incrementX();
    };
}

// In an implementation file
namespace Namespace {
    void Class::incrementX() {    // Using scope resolution to get to the class member when we aren't using an instance
        ++(this->x);              // this is a pointer, so using ->. Equivalent to ++((*this).x)
    }
}

// In a separate file lies your main method
int main() {
    Namespace::Class myInstance;   // instantiates an instance. Note the scope resolution
    Namespace::Class *myPointer = new Namespace::Class;
    myInstance.incrementX();       // Calling a function on an object instance.
    myPointer->incrementX();       // Calling a function on an object pointer.
    (*myPointer).incrementX();     // Calling a function on an object pointer by dereferencing first

    return 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X