Site de Jean-Michel RICHER

Maître de Conférences en Informatique à l'Université d'Angers

Ce site est en cours de reconstruction certains liens peuvent ne pas fonctionner ou certaines images peuvent ne pas s'afficher.


stacks

1. Introduction au C++

1.6. Classe, données membres, méthodes

1.6.1. Vocabulaire

La classe permet l'encapsulation des données qui consiste à cacher les données d'une classe aux autres classes. Les données doivent alors être accédées par les méthodes (fonctions membres) de la classe.

 Langage C   Langage C++ 
 structure   classe / objet 
 attribut / champ   donnée membre 
 sous-programme   méthode / fonction membre 
Vocabulaire lié aux classes

1.6.2. Déclaration d'une classe de base (classe mère)

Lors de la déclaration de la classe, on place les données membres, les méthodes, ... dans différentes sections qui imposent des restrictions d'accés :

  • public : les données membres et méthodes sont accessibles en dehors de la classe
  • protected : les données membres et méthodes sont accessibles par les classes qui héritent de cette classe
  • private : les données membres et méthodes sont accessibles uniquement par la classe qui les déclare
Afficher le code
  1. class Nom {
  2. public:
  3.   // données membres, méthodes, types
  4.   // visibles ou accessibles en dehors de la classe
  5.   ...
  6. protected:
  7.   // données membres, méthodes, types
  8.   // visibles ou accessibles par héritage
  9.   ...
  10. private:
  11.   // données membres, méthodes, types
  12.   // accessibles par la classe uniquement
  13.   ...
  14.  
  15. };

On peut déclarer la classe :

  • dans un seul fichier entête .h par exemple
Afficher le code    ens/inra/c1_class_person.cpp
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4.  
  5. /**
  6.  * Definition of a Person
  7.  * identified by its name and age
  8.  */
  9. class Person {
  10. // ==============================================
  11. // data members
  12. // ==============================================
  13. protected:
  14.   // name of the person (default value is empty string)
  15.   string name;
  16.   // age of the person (default value is 0)
  17.   int age;
  18.  
  19. // ==============================================
  20. // methods
  21. // ==============================================
  22. public:
  23.   /**
  24.    * default constructor
  25.    */
  26.   Person() {
  27.     name = "";
  28.     age = 0;
  29.   }
  30.  
  31.   /**
  32.    * constructor with 2 arguments
  33.    * @param n name of the person
  34.    * @param a age of the person
  35.    */
  36.   Person(string n, int a) {
  37.     name = n;
  38.     age = a;
  39.   }
  40.  
  41.   /**
  42.    * getter for name
  43.    * @return name of the person
  44.    */
  45.   string get_name() {
  46.     return name;
  47.   }
  48.  
  49.   /**
  50.    * getter for age
  51.    * @return age of the person
  52.    */
  53.   int get_age() {
  54.     return age;
  55.   }
  56.  
  57.   /**
  58.    * setter for name
  59.    * @param n name of the person
  60.    */
  61.   void set_name(string n) {
  62.     name = n;
  63.   }
  64.  
  65.   /**
  66.    * setter for age
  67.    * @param a age of the person
  68.    */
  69.   void set_age(int a) {
  70.     age = a;
  71.   }
  72.  
  73.   /**
  74.    * print class contents
  75.    * @param output stream reference
  76.    * @return output stream reference
  77.    */
  78.   ostream& print(ostream& out) {
  79.     out << name << ", " << age;
  80.     return out;
  81.   }
  82.  
  83.   friend ostream& operator<<(ostream& out, Person& p) {
  84.     return p.print(out);
  85.   }
  86. };
  87.  

  • ou dans deux fichiers :
    • un fichier entête .h qui représente l'interface
    • un fichier .cpp qui représente implantation
  • Afficher le code    ens/inra/c1_class_person_interface.h
    1. #ifndef PERSON_H
    2. #define PERSON_H
    3.  
    4. #include <iostream>
    5. #include <string>
    6. using namespace std;
    7.  
    8. /**
    9.  * Definition of a Person
    10.  * identified by its name and age
    11.  */
    12. class Person {
    13. // ==============================================
    14. // data members
    15. // ==============================================
    16. protected:
    17.   // name of the person (default value is empty string)
    18.   string name;
    19.   // age of the person (default value is 0)
    20.   int age;
    21.  
    22. // ==============================================
    23. // methods
    24. // ==============================================
    25. public:
    26.   /**
    27.    * default constructor
    28.    */
    29.   Person();
    30.  
    31.   /**
    32.    * constructor with 2 arguments
    33.    * @param n name of the person
    34.    * @param a age of the person
    35.    */
    36.   Person(string n, int a);
    37.  
    38.   /**
    39.    * getter for name
    40.    * @return name of the person
    41.    */
    42.   string get_name();
    43.  
    44.   /**
    45.    * getter for age
    46.    * @return age of the person
    47.    */
    48.   int get_age();
    49.  
    50.   /**
    51.    * setter for name
    52.    * @param n name of the person
    53.    */
    54.   void set_name(string n);
    55.  
    56.   /**
    57.    * setter for age
    58.    * @param a age of the person
    59.    */
    60.   void set_age(int a);
    61.  
    62.   /**
    63.    * print class contents
    64.    * @param output stream reference
    65.    * @return output stream reference
    66.    */
    67.   ostream& print(ostream& out);
    68.  
    69.   friend ostream& operator<<(ostream& out, Person& p) {
    70.     return p.print(out);
    71.   }
    72. };
    73.  
    74. #endif
    75.  
    Afficher le code    ens/inra/c1_class_person_implementation.cpp
    1. #include "person.h"
    2.  
    3. // default constructor
    4. Person::Person() {
    5.   name = "";
    6.   age = 0;
    7. }
    8.  
    9. // constructor with 2 arguments
    10. Person::Person(string n, int a) {
    11.   name = n;
    12.   age = a;
    13. }
    14.  
    15. // getter for name
    16. string Person::get_name() {
    17.   return name;
    18. }
    19.  
    20. // getter for age
    21. int Person::get_age() {
    22.   return age;
    23. }
    24.  
    25. // setter for name
    26. void Person::set_name(string n) {
    27.   name = n;
    28. }
    29.  
    30. // setter for age
    31. void Person::set_age(int a) {
    32.   age = a;
    33. }
    34.  
    35. // display class
    36. ostream& Person::print(ostream& out) {
    37.   out << name << ", " << age;
    38.   return out;
    39. }
    40.  
    41.  

    1.6.3. Typage : typeid, typeinfo

    L'opérateur typeid du C++ permet de connaître le type d'un objet :

    Afficher le code    ens/inra/c1_class_typeid.cpp
    1. #include <iostream>
    2. #include <string>
    3. #include <typeinfo>
    4. #include <cstdio>
    5. using namespace std;
    6.  
    7. class Base {
    8. };
    9.  
    10. class Derived : public Base {
    11. };
    12.  
    13.  
    14. int main() {
    15.   int integer = 1;
    16.   float real32 = 3.14;
    17.   int *ptr_integer = &integer;
    18.  
    19.   cout << "type of integer = " << typeid(integer).name() << endl;
    20.   cout << "type of real32  = " << typeid(real32).name() << endl;
    21.   cout << "type of ptr_integer = " << typeid(ptr_integer).name() << endl;
    22.  
    23.   const std::type_info& r1 = typeid(cout << integer);
    24.   cout << endl;
    25.     cout << "'cout<< integer' has type : " << r1.name() << endl;
    26.    
    27.     const std::type_info& r2 = typeid( printf("%f\n", real32) );
    28.     cout << "'printf(\"%f\\n\", real32)' has type : " << r2.name() << endl;
    29.    
    30.     Base b;
    31.     Derived d;
    32.    
    33.     cout << "type of b = " << typeid(b).name() << endl;
    34.     cout << "type of d = " << typeid(d).name() << endl;
    35.    
    36.     Base *p = (Base *) &b;
    37.     cout << "type of p = " << typeid(p).name() << endl;
    38.     Base *q = (Base *) &d;
    39.     cout << "type of q = " << typeid(q).name() << endl;
    40.     cout << "type of *q = " << typeid(*q).name() << endl;
    41.    
    42.     if (typeid(p) == typeid(q)) {
    43.       cout << "p and q are the same" << endl;
    44.     }
    45.    
    46.     if (typeid(*p) == typeid(*q)) {
    47.       cout << "*p and *q are the same" << endl;
    48.     } else {
    49.       cout << "*p and *q are different" << endl;
    50.     }
    51.    
    52.   return 0;
    53. }
    54.  
    type of integer = i
    type of real32  = f
    type of ptr_integer = Pi
    1
    'cout<< integer' has type : So
    'printf("%f\n", real32)' has type : i
    type of b = 4Base
    type of d = 7Derived
    type of p = P4Base
    type of q = P4Base
    type of *q = 4Base
    p and q are the same
    *p and *q are the same
    

    1.6.4. Les Constructeurs

    Les constructeurs sont appelés lors de la déclaration d'une variable du type de la classe :

    Afficher le code    ens/inra/c1_class_cons.cpp
    1. #include <string>
    2. #include <iostream>
    3. using namespace std;
    4.  
    5. class Person {
    6. protected:
    7.   string name;
    8.   int age;
    9.  
    10. public:
    11.   /**
    12.    * default constructor with no argument
    13.    */
    14.   Person() {
    15.     name = "";
    16.     age = 0;
    17.   }
    18.  
    19.   /**
    20.    * constructor with name
    21.    * @param n name of the person
    22.    */
    23.   Person(string n) {
    24.     name = n;
    25.     age = 0;
    26.   }
    27.  
    28.   /**
    29.    * constructor with name and age
    30.    * @param n name of the person
    31.    * @param a age of the person
    32.    */
    33.   Person(string n, int a) {
    34.     name = n;
    35.     age = a;
    36.   }
    37.  
    38.   /**
    39.    * print class contents
    40.    * @param output stream reference
    41.    * @return output stream reference
    42.    */
    43.   ostream& print(ostream& out) {
    44.     out << name << ", " << age;
    45.     return out;
    46.   }
    47.  
    48.   friend ostream& operator<<(ostream& out, Person& p) {
    49.     return p.print(out);
    50.   }
    51. };
    52.  
    53. // ====================================
    54. // main function
    55. // ====================================
    56. int main() {
    57.   // call of Person()
    58.   // Note: don't use Person p1(); remove parenthesis
    59.   Person p1;
    60.  
    61.   // call of Person(string n)
    62.   Person p2("toto");
    63.  
    64.   // call of Person(string n, int a)
    65.   Person p3("toto", 10);
    66.  
    67.   // define array of Persons
    68.   Person *tab;
    69.  
    70.   // create an array of Persons, call default constructor
    71.   tab = new Person[10];
    72.  
    73.   // call  constructor Person(string n, int a) -std=c++11
    74.   tab = new Person[10] { Person("toto", 10) };
    75.  
    76.   for (int i=0; i<10; ++i) {
    77.     cout << tab[i] << endl;
    78.   }
    79.  
    80.   return 0;
    81. }
    82.  

    tableaux d'objets

    Lors de l'allocation d'un tableau d'objets, chacun des objets est initialisé avec le constructeur approprié. S'il n'en existe aucun, une erreur est générée (C++11 avec liste d'initialisation).

    tab = new Person[10] { Person("toto", 10) };
    

    Mot clé explicit

    Il est recommandé dorénavant d'utiliser le mot clé explicit devant les constructeurs qui comportent un argument afin d'éviter les conversions implicites et éventuellement donner des effets de bord indésirables.

    exemple avec nombre complexe

    Afficher le code    ens/inra/c1_class_explicit_1.cpp
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. /**
    5.  * class to implement complex number
    6.  */
    7. class Complex {
    8.   double real, imag;
    9.  
    10. public:
    11.   /**
    12.    * default constructor with no argument
    13.    */
    14.   Complex() : real(0), imag(0) {
    15.     cout << "call default constructor" << endl;
    16.   }
    17.  
    18.   /**
    19.    * copy constructor
    20.    */
    21.   Complex(const Complex& c) {
    22.     real = c.real;
    23.     imag = c.imag;
    24.   }
    25.  
    26.   /**
    27.    * constructor with 2 arguments but one is assigned !
    28.    */
    29.   Complex( double r, double i = 0.0) {
    30.     cout << "call constructor with  two arguments: real=" << r
    31.       << ", imag=" << i << endl;
    32.     real = r; imag = i;
    33.   }
    34.  
    35.     /**
    36.      * overloading of addition operator
    37.      */
    38.   Complex operator+(const Complex& c) {
    39.     double tmp_real = real + c.real;
    40.     double tmp_imag = imag + c.imag;
    41.     return Complex(tmp_real, tmp_imag);
    42.     }
    43.  
    44.   bool operator==(Complex rhs) {
    45.     return (real == rhs.real && imag == rhs.imag) ? true : false;
    46.   }
    47.    
    48.   friend ostream& operator<<(ostream& out, Complex& c) {
    49.     out << "(" << c.real << "," << c.imag << ")";
    50.   }
    51. };
    52.  
    53.  
    54. int main() {
    55.   Complex one(1);
    56.     Complex sum;
    57.    
    58.   cout << one << endl;
    59.  
    60.   // implicit conversion of 3 into Complex(3, 0)
    61.   sum = one + 3;
    62.  
    63.   cout << sum << endl;
    64.  
    65.     // implicit conversion of 4 into Complex(4, 0)
    66.     if (sum == 4.0) {
    67.       cout << "result is valid" << endl;
    68.     } else {
    69.       cout << "error !!!" << endl;
    70.     }
    71.    
    72.   return 0;
    73. }
    74.  
    call constructor with  two arguments: real=1, imag=0
    call default constructor
    (1,0)
    call constructor with  two arguments: real=3, imag=0
    call constructor with  two arguments: real=4, imag=0
    (4,0)
    call constructor with  two arguments: real=4, imag=0
    result is valid
    
    Afficher le code    ens/inra/c1_class_explicit_2.cpp
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. /**
    5.  * class to implement complex number
    6.  */
    7. class Complex {
    8.   double real, imag;
    9.  
    10. public:
    11.   /**
    12.    * default constructor with no argument
    13.    */
    14.   Complex() : real(0), imag(0) {
    15.     cout << "call default constructor" << endl;
    16.   }
    17.  
    18.   /**
    19.    * copy constructor
    20.    */
    21.   Complex(const Complex& c) {
    22.     real = c.real;
    23.     imag = c.imag;
    24.   }
    25.  
    26.   /**
    27.    * constructor with 2 arguments but one is assigned !
    28.    * declared explicit !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    29.    */
    30.   explicit Complex( double r, double i = 0.0) {
    31.     cout << "call constructor with  two arguments: real=" << r
    32.       << ", imag=" << i << endl;
    33.     real = r; imag = i;
    34.   }
    35.  
    36.     /**
    37.      * overloading of addition operator
    38.      */
    39.   Complex operator+(const Complex& c) {
    40.     double tmp_real = real + c.real;
    41.     double tmp_imag = imag + c.imag;
    42.     return Complex(tmp_real, tmp_imag);
    43.     }
    44.  
    45.   bool operator==(Complex rhs) {
    46.     return (real == rhs.real && imag == rhs.imag) ? true : false;
    47.   }
    48.    
    49.   friend ostream& operator<<(ostream& out, Complex& c) {
    50.     out << "(" << c.real << "," << c.imag << ")";
    51.   }
    52. };
    53.  
    54.  
    55. int main() {
    56.   Complex one(1);
    57.     Complex sum;
    58.    
    59.   cout << one << endl;
    60.  
    61.   // *** explicit *** conversion of 3 into Complex(3, 0)
    62.   sum = one + Complex(3);
    63.  
    64.   cout << sum << endl;
    65.  
    66.     // *** explicit *** conversion of 4 into Complex(4, 0)
    67.     if (sum == Complex(4.0)) {
    68.       cout << "result is valid" << endl;
    69.     } else {
    70.       cout << "error !!!" << endl;
    71.     }
    72.    
    73.   return 0;
    74. }
    75.  

    exemple avec chaine de caractères

    Voici un autre exemple pour lequel on obtient un résultat erroné : une chaine de 120 caractères car le code ASCII de 'x' vaut 120. :

    Afficher le code    ens/inra/c1_class_cons_explicit.cpp
    1. #include <iostream>
    2. #include <cstring>
    3.  
    4. using namespace std;
    5.  
    6. class MyString {
    7. private:
    8.     int size;
    9.     char *str;
    10.  
    11. public:
    12.     // Default constructor
    13.     /* explicit */ MyString(int n) {
    14.       int i;
    15.       size = n;
    16.       str = new char [size+1];
    17.       for (i=0; i<size; ++i) str[i] = '.';
    18.       str[i] = '\0';
    19.     }
    20.  
    21.     // A method to compare two Complex numbers
    22.     MyString(char *p) {
    23.       size = strlen(p);
    24.       str = p;
    25.     }
    26.    
    27.   friend ostream& operator<<(ostream& out, MyString& s) {
    28.     out << "(" << s.size << ") " << s.str << endl;
    29.     return out;
    30.   }
    31. };
    32.  
    33. int main() {
    34.   MyString s = 'x';
    35.  
    36.   cout << s << endl;
    37.   return 0;
    38. }
    39.  

    (120) ...............................................................................
    .........................................
    

    Le même exemple avec conversion explcite :

    Afficher le code    ens/inra/c1_class_explicit_2.cpp
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. /**
    5.  * class to implement complex number
    6.  */
    7. class Complex {
    8.   double real, imag;
    9.  
    10. public:
    11.   /**
    12.    * default constructor with no argument
    13.    */
    14.   Complex() : real(0), imag(0) {
    15.     cout << "call default constructor" << endl;
    16.   }
    17.  
    18.   /**
    19.    * copy constructor
    20.    */
    21.   Complex(const Complex& c) {
    22.     real = c.real;
    23.     imag = c.imag;
    24.   }
    25.  
    26.   /**
    27.    * constructor with 2 arguments but one is assigned !
    28.    * declared explicit !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    29.    */
    30.   explicit Complex( double r, double i = 0.0) {
    31.     cout << "call constructor with  two arguments: real=" << r
    32.       << ", imag=" << i << endl;
    33.     real = r; imag = i;
    34.   }
    35.  
    36.     /**
    37.      * overloading of addition operator
    38.      */
    39.   Complex operator+(const Complex& c) {
    40.     double tmp_real = real + c.real;
    41.     double tmp_imag = imag + c.imag;
    42.     return Complex(tmp_real, tmp_imag);
    43.     }
    44.  
    45.   bool operator==(Complex rhs) {
    46.     return (real == rhs.real && imag == rhs.imag) ? true : false;
    47.   }
    48.    
    49.   friend ostream& operator<<(ostream& out, Complex& c) {
    50.     out << "(" << c.real << "," << c.imag << ")";
    51.   }
    52. };
    53.  
    54.  
    55. int main() {
    56.   Complex one(1);
    57.     Complex sum;
    58.    
    59.   cout << one << endl;
    60.  
    61.   // *** explicit *** conversion of 3 into Complex(3, 0)
    62.   sum = one + Complex(3);
    63.  
    64.   cout << sum << endl;
    65.  
    66.     // *** explicit *** conversion of 4 into Complex(4, 0)
    67.     if (sum == Complex(4.0)) {
    68.       cout << "result is valid" << endl;
    69.     } else {
    70.       cout << "error !!!" << endl;
    71.     }
    72.    
    73.   return 0;
    74. }
    75.  

    1.6.5. Le Destructeur

    Il n'existe qu'un seul destructeur qui est chargé de libérer les ressources allouées ou utilisées par le/les constructeur(s).

    le destructeur ne possède aucun argument.

    le destructeur est dorénavant déclaré virtuel en cas d'héritage afin de permettre l'appel de la série des destructeurs.

    afin de permettre l'utilisation de dynamic_cast il faut qu'il y est une méthode virtuelle.

    si aucun destructeur n'est déclaré le compilateur en crée un par défaut (C++11)

    Afficher le code    ens/inra/c1_class_destr.cpp
    1. /**
    2.  * Definition of a Vector of integers
    3.  */
    4. class Vector {
    5. // ==============================================
    6. // data members
    7. // ==============================================
    8. protected:
    9.   // maximum number of elements
    10.   int max_elements;
    11.   // storage for the elements allocated dynamically
    12.   int *elements;
    13.  
    14. // ==============================================
    15. // methods
    16. // ==============================================
    17. public:
    18.   /**
    19.    * constructor with initial size in number of elements
    20.    * @param me maximum number of elements
    21.    */
    22.   Vector(int me) {
    23.     max_elements = me;
    24.     elements = new int [ max_elements ];
    25.   }
    26.  
    27.   /**
    28.    * destructor
    29.    */
    30.   virtual ~Vector() {
    31.     delete [] elements;
    32.   }
    33. };
    34.  

    1.6.6. Constructeur par recopie

    Le constructeur par recopie (copy constructor) est utilisé lorsqu'un constructeur prend en paramètre un élément de la même classe que lui : la nouvelle instance de la classe sera crée à partir de l'instance existante, il s'agit généralement d'une copie, d'où l'appellation de copy constructor

    Vector v1(100);
    // create copy of v1
    Vector v2(v1);
    

    Le constructeur par recopie doit être déclaré de type : T(const T& )

    Note: il existe un constructeur par recopie par défaut qui recopie les valeurs des données membres de v1 dans v2, ce qui peut mener à faire crasher le programme.

    copy constructor default and user-defined

    Afficher le code    ens/inra/c1_class_cons_copy.cpp
    1. /**
    2.  * Definition of a Vector of integers
    3.  */
    4. class Vector {
    5. // ==============================================
    6. // data members
    7. // ==============================================
    8. protected:
    9.   // maximum number of elements
    10.   int max_elements;
    11.   // storage for the elements allocated dynamically
    12.   int *elements;
    13.  
    14. // ==============================================
    15. // methods
    16. // ==============================================
    17. public:
    18.   /**
    19.    * constructor with initial size in number of elements
    20.    * @param me maximum number of elements
    21.    */
    22.   Vector(int me) {
    23.     max_elements = me;
    24.     elements = new int [ max_elements ];
    25.   }
    26.  
    27.   /**
    28.    * destructor
    29.    */
    30.   virtual ~Vector() {
    31.     delete [] elements;
    32.   }
    33.  
    34.   /**
    35.    * copy constructor
    36.    */
    37.   Vector(const Vector& v) {
    38.     max_elements = v.max_elements;
    39.     elements = new int [ max_elements ];
    40.     memcpy(elements, v.elements, max_elements * sizeof(int));
    41.   }
    42.  
    43. };
    44.  

    1.6.7. Opérateur d'affectation

    L'opérateur d'affectation doit être redéfini pour certaines classes, notamment si la classe alloue des données. Il est utilisé dans le cas suivant :

    Vector v1(100);
    Vector v2(250);
    
    v2 = v1;
    

    D'un point de vue sémantique, il réalise le traitement du destructeur suivi du traitement du constructeur par recopie.

    Note: il existe un opérateur d'affectation par défaut qui recopie les valeurs des données membres de v1 dans v2.

    Il doit être déclaré de type : T& operator=(const T& )

    Afficher le code    ens/inra/c1_class_assignment_op.cpp
    1. /**
    2.  * Definition of a Vector of integers
    3.  */
    4. class Vector {
    5. // ==============================================
    6. // data members
    7. // ==============================================
    8. protected:
    9.   // maximum number of elements
    10.   int max_elements;
    11.   // storage for the elements allocated dynamically
    12.   int *elements;
    13.  
    14. // ==============================================
    15. // methods
    16. // ==============================================
    17. public:
    18.   /**
    19.    * constructor with initial size in number of elements
    20.    * @param me maximum number of elements
    21.    */
    22.   Vector(int me) {
    23.     max_elements = me;
    24.     elements = new int [ max_elements ];
    25.   }
    26.  
    27.   /**
    28.    * destructor
    29.    */
    30.   virtual ~Vector() {
    31.     delete [] elements;
    32.   }
    33.  
    34.   /**
    35.    * copy constructor
    36.    */
    37.   Vector(const Vector& v) {
    38.     max_elements = v.max_elements;
    39.     elements = new int [ max_elements ];
    40.     memcpy(elements, v.elements, max_elements * sizeof(int));
    41.   }
    42.  
    43.   /**
    44.    * assignment operator
    45.    */
    46.   Vector& operator=(const Vector& v) {
    47.     // verifiy that we are not assigning the Vector to itself !!
    48.     if (&v != this) {
    49.       // destroy data previously allocated
    50.       delete [] elements;
    51.       // recreate a copy
    52.       max_elements = v.max_elements;
    53.       elements = new int [ max_elements ];
    54.       memcpy(elements, v.elements, max_elements * sizeof(int));
    55.     }
    56.     return *this;
    57.   }
    58.  
    59. };
    60.  

    1.6.8. Getters et setters

    Les getters sont les méthodes qui permettent de récupérer la valeur des données membres.

    Les setters sont les méthodes qui permettent d'attribuer une valeur aux données membres.

    Afficher le code    ens/inra/c1_class_getters_setters.cpp
    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4.  
    5. class Person {
    6. protected:
    7.   string name;
    8.   int age;
    9.  
    10. public:
    11.   Person() {
    12.     name = "";
    13.     age = 0;
    14.   }
    15.   Person(string n, int a) {
    16.     name = n;
    17.     age = a;
    18.   }
    19.  
    20.   // ********
    21.   // getters
    22.   // ********
    23.   string get_name() {
    24.     return name;
    25.   }
    26.  
    27.   int get_age() {
    28.     return age;
    29.   }
    30.  
    31.   // ********
    32.   // setters
    33.   // ********
    34.   void set_name(string n) {
    35.     name = n;
    36.   }
    37.  
    38.   void set_age(int a) {
    39.     age = a;
    40.   }
    41. };
    42.  

    1.6.9. Affichage

    On redéfinit l'opérateur << qui appelle une méthode print, cette dernière peut être déclarée virtuelle (cf méthode virtuelle) si on crée une hiérarchie de classe à partir de la classe de base.

    Afficher le code    ens/inra/c1_class_person.cpp
    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4.  
    5. /**
    6.  * Definition of a Person
    7.  * identified by its name and age
    8.  */
    9. class Person {
    10. // ==============================================
    11. // data members
    12. // ==============================================
    13. protected:
    14.   // name of the person (default value is empty string)
    15.   string name;
    16.   // age of the person (default value is 0)
    17.   int age;
    18.  
    19. // ==============================================
    20. // methods
    21. // ==============================================
    22. public:
    23.   /**
    24.    * default constructor
    25.    */
    26.   Person() {
    27.     name = "";
    28.     age = 0;
    29.   }
    30.  
    31.   /**
    32.    * constructor with 2 arguments
    33.    * @param n name of the person
    34.    * @param a age of the person
    35.    */
    36.   Person(string n, int a) {
    37.     name = n;
    38.     age = a;
    39.   }
    40.  
    41.   /**
    42.    * getter for name
    43.    * @return name of the person
    44.    */
    45.   string get_name() {
    46.     return name;
    47.   }
    48.  
    49.   /**
    50.    * getter for age
    51.    * @return age of the person
    52.    */
    53.   int get_age() {
    54.     return age;
    55.   }
    56.  
    57.   /**
    58.    * setter for name
    59.    * @param n name of the person
    60.    */
    61.   void set_name(string n) {
    62.     name = n;
    63.   }
    64.  
    65.   /**
    66.    * setter for age
    67.    * @param a age of the person
    68.    */
    69.   void set_age(int a) {
    70.     age = a;
    71.   }
    72.  
    73.   /**
    74.    * print class contents
    75.    * @param output stream reference
    76.    * @return output stream reference
    77.    */
    78.   ostream& print(ostream& out) {
    79.     out << name << ", " << age;
    80.     return out;
    81.   }
    82.  
    83.   friend ostream& operator<<(ostream& out, Person& p) {
    84.     return p.print(out);
    85.   }
    86. };
    87.