C++ Accesso ai membri della classe


Esempio

Per accedere alle variabili membro e alle funzioni membro di un oggetto di una classe, il . operatore è usato:

struct SomeStruct {
  int a;
  int b;
  void foo() {}
};

SomeStruct var;
// Accessing member variable a in var.
std::cout << var.a << std::endl;
// Assigning member variable b in var.
var.b = 1;
// Calling a member function.
var.foo();

Quando si accede ai membri di una classe tramite un puntatore, viene comunemente utilizzato l'operatore -> . In alternativa, l'istanza può essere dereferenziata e il . operatore utilizzato, anche se questo è meno comune:

struct SomeStruct {
  int a;
  int b;
  void foo() {}
};

SomeStruct var;
SomeStruct *p = &var;
// Accessing member variable a in var via pointer.
std::cout << p->a << std::endl;
std::cout << (*p).a << std::endl;
// Assigning member variable b in var via pointer.
p->b = 1;
(*p).b = 1;
// Calling a member function via a pointer.
p->foo();
(*p).foo();

Quando si accede a membri di classi statiche, viene utilizzato l'operatore :: , ma sul nome della classe anziché un'istanza di esso. In alternativa, è possibile accedere al membro statico da un'istanza o da un puntatore a un'istanza utilizzando . o -> operatore, rispettivamente, con la stessa sintassi dell'accesso a membri non statici.

struct SomeStruct {
  int a;
  int b;
  void foo() {}

  static int c;
  static void bar() {}
};
int SomeStruct::c;

SomeStruct var;
SomeStruct* p = &var;
// Assigning static member variable c in struct SomeStruct.
SomeStruct::c = 5;
// Accessing static member variable c in struct SomeStruct, through var and p.
var.a = var.c;
var.b = p->c;
// Calling a static member function.
SomeStruct::bar();
var.bar();
p->bar();

sfondo

L'operatore -> è necessario perché l'operatore di accesso membro . ha la precedenza sull'operatore di dereferenziazione * .

Ci si aspetterebbe che *pa avrebbe la dereferenziazione p (risultante in un riferimento all'oggetto p sta puntando a) e quindi l'accesso al suo membro a . Ma in effetti, tenta di accedere al membro a di p e quindi dereferenziarlo. Ie *pa è equivalente a *(pa) . Nell'esempio sopra, ciò comporterebbe un errore del compilatore a causa di due fatti: in primo luogo, p è un puntatore e non ha un membro a . In secondo luogo, a è un numero intero e, quindi, non può essere dereferenziato.

La soluzione non comune a questo problema sarebbe quella di controllare esplicitamente la precedenza: (*p).a

Invece, l'operatore -> è quasi sempre usato. È una scorciatoia per il primo dereferenziamento del puntatore e quindi per accedervi. Cioè (*p).a è esattamente uguale a p->a .

L'operatore :: è l'operatore dell'ambito, utilizzato nello stesso modo dell'accesso a un membro di uno spazio dei nomi. Questo perché un membro di classe statico è considerato presente nello scope di quella classe, ma non è considerato un membro delle istanze di quella classe. L'uso del normale . e -> è consentito anche per i membri statici, nonostante non siano membri di istanze, per ragioni storiche; questo è utile per scrivere codice generico nei template, poiché il chiamante non deve preoccuparsi se una data funzione membro è statica o non statica.