Initialisation de classe

De RAD Studio
Aller à : navigation, rechercher

Remonter à Constructeurs - Index


Un objet de classe avec des membres public et aucun constructeur ni classe de base (généralement une structure), peut être initialisé avec une liste de valeurs d'initialisation. Si une classe a un constructeur, ses objets doivent être initialisés ou posséder un constructeur implicite. Ce dernier est utilisé pour des objets non initialisés explicitement par le programmeur.

Les objets des classes avec constructeurs peuvent être initialisés avec une liste d'expressions mise entre parenthèses. La liste sert de liste d'arguments au constructeur. Il est aussi possible d'utiliser un signe égal suivi d'une valeur unique. Cette dernière peut être du même type que le premier argument accepté par un constructeur de cette classe, auquel cas soit il n'existe pas d'autre argument, soit les arguments restants ont des valeurs implicites. La valeur unique peut aussi être un objet du même type que la classe. Dans le premier cas, le constructeur correspondant est appelé pour créer l'objet. Dans le deuxième cas, le constructeur copie est appelé pour initialiser l'objet.

class X
{
  int i;
public:
  X();         // function bodies omitted for clarity
  X(int x);
  X(const X&);
};
void main()
{
  X one;        // default constructor invoked
  X two(1);     // constructor X::X(int) is used
  X three = 1;  // calls X::X(int)
  X four = one; // invokes X::X(const X&) for copy
  X five(two);  // calls X::X(const X&)
}

Le constructeur peut affecter des valeurs à ses membres de deux manières :

1. soit en acceptant les valeurs comme paramètres, et en effectuant des affectations aux variables membres dans le corps de la fonction du constructeur :

class X
{
  int a, b;
public:
  X(int i, int j) { a = i; b = j }
};

2. soit en utilisant une liste de valeurs d'initialisation avant le corps de la fonction :

class X
{
  int a, b, &c;  // Note the reference variable.
public:
  X(int i, int j) : a(i), b(j), c(a) {}
};

La liste de valeurs d'initialisation est le seul endroit où référencer une variable référence.

Dans les deux cas, une initialisation de X x(1, 2) affecte la valeur 1 à x::a et 2 à x::b. La deuxième méthode (liste de valeurs d'initialisation) permet de transmettre des valeurs aux constructeurs des classes de base.

Remarque :  Les constructeurs des classes de base doivent être déclarés public ou protected pour être appelés depuis une classe dérivée.

class base1
{
  int x;
public:
  base1(int i) { x = i; }
};
class base2
{
  int x;
public:
  base2(int i) : x(i) {}
};
class top : public base1, public base2
{
  int a, b;
public:
  top(int i, int j) : base1(i*5), base2(j+i), a(i) { b = j;}
};

Avec cette hiérarchie de classe, une déclaration de type top one(1, 2) aboutit à l'initialisation de base1 à la valeur 5, et de base2 à la valeur 3. Il est possible de combiner les méthodes d'initialisation.

Comme nous venons de le voir, les classes de base sont initialisées dans l'ordre des déclarations. Les membres sont ensuite initialisés, également dans l'ordre des déclarations, et indépendamment de la liste des valeurs d'initialisation.

class X
{
  int a, b;
public:
  X(int i, j) :  a(i), b(a+j) {}
};

Avec cette classe, la déclaration X x(1, 2) affecte la valeur 1 à x::a et 2 à x::b.

Les constructeurs des classes de base sont appelés avant la construction des membres des classes dérivées. Si les valeurs de la classe dérivée sont modifiées, elles ne se répercutent pas sur la création de la classe de base.

class base
{
  int x;
public:
  base(int i) : x(i) {}
};
class derived : base
{
  int a;
public:
  derived(int i) : a(i*10), base(a) { } // Watch out! Base will be
                                        // passed an uninitialized 'a' };

Avec cette définition de classe, un appel de la classe derived d(1) ne donnera pas la valeur 10 pour le membre x de la classe de base. La valeur transmise au constructeur de la classe de base restera non définie.

Si vous voulez inclure une liste de valeurs d'initialisation dans un constructeur qui n'est pas inline, ne la placez pas dans la définition de classe. Placez-la à l'endroit où la fonction est définie.

derived::derived(int i) : a(i)
{
  // …
}

Voir aussi