Chapitre 6 : références conversion implicite pour construsteur, liste initialisation

Références

Si AA est une expression d'un type, on peut définir une référence (simple) sur AA avec la syntaxe A&.

On peut imaginer une référence comme un pointeur avec un traitement synthaxique particulier.

int a;
int &r = a; //pensez : int* const r = &a;

//int &r2 = 5; //erreur : &5 n'a pas de sens

a = 1;
printf("%d",r); //affiche 1

r = 2; // pensez : *r = 2
printf("%d",a); //affiche 2

Référence en paramètre

void f(int a){
  a = 5;
}

void g(int &a){
  a = 5;
}

int main(){
  int c = 1;
  f(c);
  printf("%d",c); //1
  g(c);
  printf("%d",c); //5
}

En tant que type de retour de fonction

int g_num = 3;
  int& h(int c){
  g_num = g_num + c;
  return g_num; //&g_num; est correct
}

int main(){
  int u = h(5);
  h(5) = 7; //équivalent à g_num = 7;
  int* p = &h(5); // équivalent à &g_num;
}

Constructeurs et conversion

Soit C l'identifiant d'une classe et T une expression de type s'il existe un constructeur de signature C(T) alors se met en place une conversion implicite du type T vers le type C (qui utilise le constructeur en question.

class A{
  ...
  public:
    A(int a){
      ...
  }
};

void f(A p){
  ...
}

int main(){
  A obj{3}; //appel à A(3);
  A obj2{3}; //appel à A(3);
  f(5); //appel à A(5) pour construire le paramètre p
}

Explicite

Pour éviter cette mise en place on peut déclarer explicit (mot-clé) le constructeur

Liste d'initialisation

Dans un constructeur on peut expliciter les constructeurs à appeler pour construire les attirbuts membres de la classe.

Si C est le nom de la classe on écrit : C(...) : attribut1{...}, attribut2{...} {corps du constructeur}

class A{
  const int a;
  int b;
  A(int c) : a{c}, b{0} {
    b = 0; //inutile
    a = c; //erreur
}

int main(){
A u{3} // u.a = 3, u.b = 0

Remarque

On peut aussi indiquer des appels par défaut à l'endroit où l'on déclare les attributs.

class C{
  const int a{5};
  int b{0};
  public:
    C(int p) : a{3}{
      ...
    }
    C(void){
      ...
    }; //appel à a{5}
}

int main(){
  C obj;
  C obj2{5};
}

Fonctions et classes amies

On peut permettre à une fonction exterieur d'accéder aux membres privés d'une classe en la déclarant "amie" avec le mot clé friend

class C{
  private:
    int a;
    friend void f(void);
};

void f(void){
  C obj;
  obj.a = 5; // ok car f est amie

int main(){
  C obj;
  //obj.a erreur a est privé
  return 0;
}

On peut aussi déclarer amie toutes les méthodes d'une classe.

Exemple

//si B est le nom d'une classe
class A{
...
friend class B; // ou friend B;?
}