'>

les class_premier partie

Une classe est un concept élargi d'une structure de données: au lieu de tenir seules données, il peut contenir des données et des fonctions.

Un objet est une instanciation d'une classe. En termes de variables, une classe serait le type, et un objet serait la variable.

Les classes sont généralement déclarés en utilisant le mot-clé class, avec le format suivant:

 classe class_name {
   access_specifier_1:
     member1;
   access_specifier_2:
     member2;
   ...
   Object_names};


Où nom_classe est un identifiant valide pour la classe, object_names est une liste facultative de noms pour les objets de cette classe. Le corps de la déclaration peut contenir des membres, qui peuvent être soit des données ou des déclarations de fonctions, et éventuellement accéder prescripteurs.

Tout est très semblable à la déclaration sur les structures de données, sauf que nous pouvons maintenant inclure aussi des fonctions et des membres, mais aussi cette nouvelle chose appelée un spécificateur d'accès. Un spécificateur d'accès est l'un des trois mots-clés suivants: privé, public ou protégé. Ces prescripteurs modifier les droits d'accès que les membres acquièrent les suivantes:

    membres privés d'une classe sont accessibles uniquement à partir d'autres membres de la même classe ou de leurs amis.
    membres protégés sont accessibles à partir des membres de leur même classe et de leurs amis, mais aussi des membres de leurs classes dérivées.
    Enfin, les membres du public sont accessibles depuis n'importe quel endroit où l'objet est visible.


Par défaut, tous les membres d'une classe déclarée avec le mot-clé de classe ont un accès privé pour tous ses membres. Par conséquent, tout membre qui est déclaré avant une autre spécificateur de classe a automatiquement accès privé. Par exemple:

1
 2
 3
 4
 5
 6


   

 class CRectangle { int x, y; public : void set_values ( int , int ); int area ( void ); } rect;



Déclare une classe (par exemple, un type) a appelé CRectangle et un objet (par exemple, une variable) de cette classe appelée rect. Cette classe contient quatre membres: deux membres de données de type int (membre x et membre y) avec accès privé (car privé est le niveau par défaut d'accès) et deux fonctions de membre avec accès public: set_values ​​() et zone (), qui pour maintenant, nous n'avons inclus que leur déclaration, et non leur définition.

Notez la différence entre le nom de la classe et le nom de l'objet: Dans l'exemple précédent, CRectangle était le nom de la classe (par exemple, le type), tandis que rect était un objet de type CRectangle. C'est la même relation int et un avoir dans la déclaration suivante:



   

 int a;



où int est le nom du type (la classe) et a est le nom de la variable (l'objet).

Après les déclarations précédentes de CRectangle et rect, nous pouvons nous référer dans le corps du programme à l'un des membres du public de l'objet rect comme s'ils étaient des fonctions normales ou des variables normales, tout en mettant le nom de l'objet suivi d'un point (. ), puis le nom de l'élément. Tout cela est très similaire à ce que nous avons fait avec des structures de données simples avant. Par exemple:

 1
 2


   

 rect.set_values (3,4); myarea = rect.area();



Les seuls membres de rect que nous ne pouvons pas accéder à partir du corps de notre programme en dehors de la classe sont X et Y, car ils ont un accès privé et ils ne peuvent être visés à partir d'autres membres de cette même classe.

Voici un exemple complet de CRectangle de classe:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22


   

 // classes example #include <iostream> using namespace std; class CRectangle { int x, y; public : void set_values ( int , int ); int area () { return (x*y);} }; void CRectangle::set_values ( int a, int b) { x = a; y = b; } int main () { CRectangle rect; rect.set_values (3,4); cout << "area: " << rect.area(); return 0; }

   

  Superficie: 12



La plus importante chose de nouveau dans ce code est l'opérateur de portée (::, deux colons) inclus dans la définition de set_values ​​(). Il est utilisé pour définir un membre d'une classe à partir de l'extérieur de la définition de la classe elle-même.

Vous pouvez remarquer que la définition de la zone de fonction membre () a été inclus directement dans la définition de la classe CRectangle donné son extrême simplicité, alors que set_values ​​() a seulement son prototype déclarée dans la classe, mais sa définition est à l'extérieur. Dans cette définition à l'extérieur, nous devons utiliser l'opérateur de portée (::) pour spécifier que nous définissons une fonction qui est un membre de la CRectangle de classe et non une fonction globale régulière.

L'opérateur de portée (::) indique la classe à laquelle le membre appartient d'être déclaré, en accordant exactement les mêmes propriétés de portée que si cette définition de fonction a été directement inclus dans la définition de classe. Par exemple, dans les set_values ​​de fonction () du code précédent, nous avons été en mesure d'utiliser les variables x et y, qui sont membres privés de CRectangle de classe, ce qui signifie qu'ils ne sont accessibles que par les autres membres de leur classe.

La seule différence entre la définition d'une fonction membre d'une classe complètement à l'intérieur de sa classe ou de n'inclure que le prototype et plus tard sa définition, est que dans le premier cas, la fonction sera automatiquement considérée comme une fonction membre inline par le compilateur, tandis que dans le second il sera un (non-inline) fonction membre normale de classe, ce qui en fait suppose pas de différence dans le comportement.

Les membres x et y ont un accès privé (rappelez-vous que si rien d'autre n'est dit, tous les membres d'une classe définie avec la classe de mots clés ont un accès privé). En déclarant leur privé, nous refusons leur accès depuis n'importe où en dehors de la classe. Cela est logique, puisque nous avons déjà défini une fonction de membre de définir les valeurs de ces membres au sein de l'objet: les set_values ​​fonction membre (). Par conséquent, le reste du programme n'a pas besoin d'avoir un accès direct pour eux. Peut-être un exemple aussi simple que cela, il est difficile de trouver une utilité dans la protection de ces deux variables, mais en plus grand projets, il peut être très important que les valeurs ne peuvent pas être modifiées d'une manière inattendue (inattendu du point de vue de l'objet ).

Un des plus grands avantages d'une classe est que, comme n'importe quel autre type, nous pouvons déclarer plusieurs objets de celui-ci. Par exemple, à la suite de l'exemple précédent de CRectangle de classe, nous aurions déclaré le rectb de l'objet en plus de l'objet rect:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24


   

 // example: one class, two objects #include <iostream> using namespace std; class CRectangle { int x, y; public : void set_values ( int , int ); int area () { return (x*y);} }; void CRectangle::set_values ( int a, int b) { x = a; y = b; } int main () { CRectangle rect, rectb; rect.set_values (3,4); rectb.set_values (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; return 0; }

   

  zone rect: 12
  zone rectb: 30



Dans ce cas concret, la classe (type des objets) à qui nous parlons est CRectangle, dont il existe deux instances ou des objets: rect et rectb. Chacun d'eux a ses propres variables membres et les fonctions membres.

Notez que l'appel à rect.area () ne donne pas le même résultat que l'appel à rectb.area (). C'est parce que chaque objet de CRectangle de classe a ses propres variables x et y, comme eux, en quelque sorte, ont également membres de leur propre fonction Set_Value () et la région () que chacun utilise ses propres variables d'objets pour fonctionner.

C'est le concept de base de la programmation orientée objet: les données et les fonctions sont à la fois membres de l'objet. Ensembles de variables globales qui nous passer d'une fonction à l'autre en tant que paramètres, mais nous traitons des objets qui ont leurs propres données et fonctions intégrées en tant que membres nous utilisons plus. Notez que nous n'avons pas eu à donner des paramètres dans l'un des appels à rect.area ou rectb.area. Les fonctions de membre utilisées directement les données membres de leurs objets respectifs rect et rectb.

Les constructeurs et destructeurs
Objets ont généralement besoin d'initialiser des variables ou affecter la mémoire dynamique au cours de leur processus de création de devenir opérationnel et pour éviter de retourner des valeurs inattendues au cours de leur exécution. Par exemple, que se passerait-il si, dans l'exemple précédent, nous avons appelé la zone de fonction membre () avant d'avoir appelé set_values ​​d'function ()? Probablement que nous aurions obtenu un résultat indéterminé puisque les membres x et y auraient jamais été attribué une valeur.

Afin d'éviter cela, une classe peut inclure une fonction spéciale appelée constructeur, qui est automatiquement appelée à chaque fois qu'un nouvel objet de cette classe est créée. Cette fonction constructeur doit avoir le même nom que la classe, et ne peut avoir aucun type de retour, pas même annuler.

Nous allons mettre en œuvre CRectangle y compris un constructeur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23


   

 // example: class constructor #include <iostream> using namespace std; class CRectangle { int width, height; public : CRectangle ( int , int ); int area () { return (width*height);} }; CRectangle::CRectangle ( int a, int b) { width = a; height = b; } int main () { CRectangle rect (3,4); CRectangle rectb (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; return 0; }

   

  zone rect: 12
  zone rectb: 30



Comme vous pouvez le voir, le résultat de cet exemple est identique à la précédente. Mais maintenant, nous avons supprimé les set_values ​​de fonction membre (), et avons inclus à la place d'un constructeur qui effectue une action similaire: il initialise les valeurs de la largeur et de la hauteur avec les paramètres qui lui sont passés.

Remarquez comment ces arguments sont passés au constructeur au moment où les objets de cette classe sont créés:

 1
 2


   

 CRectangle rect (3,4); CRectangle rectb (5,6);



Les constructeurs peuvent pas être appelé explicitement comme s'ils étaient des fonctions membres réguliers. Ils ne sont exécutés quand un nouvel objet de cette classe est créée.

Vous pouvez également voir comment ni la déclaration de prototype du constructeur (dans la classe), ni la définition de constructeur-ci comprennent une valeur de retour, pas même annuler.

Le destructeur remplit la fonction inverse. Elle est appelée automatiquement quand un objet est détruit, soit parce que son champ d'existence a fini (par exemple, si elle a été définie comme un objet local dans une fonction et les extrémités de fonction) ou parce que c'est un objet dynamiquement assignée et il est libéré en utilisant l'opérateur delete.

Le destructeur doit avoir le même nom que la classe, mais précédée d'un tilde (~) et il doit aussi retourner aucune valeur.

L'utilisation de destructeurs est particulièrement adaptée quand un objet affecte la mémoire dynamique au cours de sa durée de vie et au moment d'être détruit, nous voulons libérer la mémoire que l'objet a été attribuée.

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30


   

 // example on constructors and destructors #include <iostream> using namespace std; class CRectangle { int *width, *height; public : CRectangle ( int , int ); ~CRectangle (); int area () { return (*width * *height);} }; CRectangle::CRectangle ( int a, int b) { width = new int ; height = new int ; *width = a; *height = b; } CRectangle::~CRectangle () { delete width; delete height; } int main () { CRectangle rect (3,4), rectb (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; return 0; }

   

  zone rect: 12
  zone rectb: 30



Constructeurs Surcharge
Comme toute autre fonction, un constructeur peut également être surchargé avec plus d'une fonction qui a le même nom mais avec différents types ou nombre de paramètres. Rappelez-vous que pour les fonctions surchargées le compilateur appellera celui dont les paramètres correspondent aux arguments utilisés dans l'appel de fonction. Dans le cas des constructeurs, qui sont appelés automatiquement quand un objet est créé, celui exécuté est celui qui correspond aux arguments passés sur la déclaration de l'objet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29


   

 // overloading class constructors #include <iostream> using namespace std; class CRectangle { int width, height; public : CRectangle (); CRectangle ( int , int ); int area ( void ) { return (width*height);} }; CRectangle::CRectangle () { width = 5; height = 5; } CRectangle::CRectangle ( int a, int b) { width = a; height = b; } int main () { CRectangle rect (3,4); CRectangle rectb; cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; return 0; }

   

  zone rect: 12
  zone rectb: 25



Dans ce cas, rectb a été déclarée sans argument, il a été initialisé avec le constructeur qui n'a pas de paramètres, qui initialise la largeur et la hauteur d'une valeur de 5.

Important: Notez comment si nous déclarons un objet nouveau et nous voulons utiliser son constructeur par défaut (celui sans paramètres), nous n'incluons pas les parenthèses ():

 1
 2


   

 CRectangle rectb; // right CRectangle rectb(); // wrong!



Constructeur par défaut
Si vous ne déclarez pas les constructeurs dans une définition de classe, le compilateur suppose la classe d'avoir un constructeur par défaut sans argument. Par conséquent, après avoir déclaré une classe comme celle-ci:

 1
 2
 3
 4
 5


   

 class CExample { public : int a,b,c; void multiply ( int n, int m) { a=n; b=m; c=a*b; } };



Le compilateur suppose que CExample possède un constructeur par défaut, de sorte que vous pouvez déclarer des objets de cette classe simplement en les déclarant sans arguments:



   

 CExample ex;



Mais dès que vous déclarez votre propre constructeur d'une classe, le compilateur ne fournit plus un constructeur par défaut implicite. Donc, vous devez déclarer tous les objets de cette classe selon les prototypes du constructeur que vous avez définies pour la classe:

 1
 2
 3
 4
 5
 6


   

 class CExample { public : int a,b,c; CExample ( int n, int m) { a=n; b=m; }; void multiply () { c=a*b; }; };



Ici, nous avons déclaré un constructeur qui prend deux paramètres de type int. Par conséquent, la déclaration de l'objet suivante est correcte:



   

 CExample ex (2,3);


Mais,



   

 CExample ex;



Ce ne serait pas correct, puisque nous avons déclaré la classe d'avoir un constructeur explicite, remplaçant ainsi le constructeur par défaut.

Mais le compilateur ne crée pas seulement un constructeur par défaut pour vous si vous n'indiquez pas votre propre. Il fournit trois fonctions spéciales pour les membres au total qui sont implicitement déclarés si vous ne déclarez pas votre propre. Il s'agit de la copie du constructeur, l'opérateur d'affectation de copie et le destructeur par défaut.

Le constructeur de copie et l'opérateur d'affectation de copie de copie de toutes les données contenues dans un autre objet pour les données membres de l'objet courant. Pour CExample, le constructeur de copie implicitement déclaré par le compilateur serait quelque chose de similaire à:

 1
 2
 3


   

 CExample::CExample ( const CExample& rv) { a=rv.a; b=rv.b; c=rv.c; }



Par conséquent, les deux déclarations d'objets suivants seraient correct:

 1
 2


   

 CExample ex (2,3); CExample ex2 (ex); // copy constructor (data copied from ex)



Les pointeurs vers des classes
Il est parfaitement valide pour créer des pointeurs qui pointent vers les classes. Nous avons tout simplement de considérer que, une fois déclarée, une classe devient un type valide, afin que nous puissions utiliser le nom de classe comme type pour le pointeur. Par exemple:



   

 CRectangle * prect;



est un pointeur vers un objet de la classe CRectangle.

Comme cela s'est produit avec les structures de données, dans le but de se référer directement à un membre d'un objet pointé par un pointeur, nous pouvons utiliser l'opérateur flèche (->) d'adressage indirect. Voici un exemple avec certaines combinaisons possibles:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34


   

 // pointer to classes example #include <iostream> using namespace std; class CRectangle { int width, height; public : void set_values ( int , int ); int area ( void ) { return (width * height);} }; void CRectangle::set_values ( int a, int b) { width = a; height = b; } int main () { CRectangle a, *b, *c; CRectangle * d = new CRectangle[2]; b= new CRectangle; c= &a; a.set_values (1,2); b->set_values (3,4); d->set_values (5,6); d[1].set_values (7,8); cout << "a area: " << a.area() << endl; cout << "*b area: " << b->area() << endl; cout << "*c area: " << c->area() << endl; cout << "d[0] area: " << d[0].area() << endl; cout << "d[1] area: " << d[1].area() << endl; delete [] d; delete b; return 0; }

   

  une zone: 2
  * B zone: 12
  * C zone: 2
  d [0] habitable: 30
  d [1] habitable: 56



Ensuite, vous avez un aperçu sur la façon dont vous pouvez lire certains pointeur et les opérateurs de la classe (*, &, -> [].) Qui apparaissent dans l'exemple précédent:

expression     peut être lu comme
* X     pointée par x
Et x     adresse de x
xy     membre y de l'objet x
x> y     membre y de l'objet pointé par x
(* X). Y     membre y de l'objet pointé par x (équivalent à la précédente)
x [0]     premier objet pointé par x
x [1]     deuxième objet pointé par x
x [n]     (N +1)-ième objet pointé par x

Soyez sûr que vous comprenez la logique sous toutes ces expressions avant de passer aux sections suivantes. Si vous avez des doutes, relisez cette section et / ou consulter les sections précédentes sur les pointeurs et les structures de données.

Classes définies avec struct et union
Les classes peuvent être définis non seulement avec la classe de mots clés, mais aussi avec des mots clés struct et union.

Les concepts de la structure de classe et les données sont tellement semblables que les deux mots clés (struct et class) peuvent être utilisés en C + + pour déclarer des classes (c.-à-struct s peut aussi avoir des membres de la fonction en C + +, non seulement les membres de données). La seule différence entre les deux est que les membres des classes déclarées avec le mot-clé struct avoir accès public par défaut, tandis que les membres des classes déclarées avec le mot-clé class ont un accès privé. Pour toutes autres fins les deux mots sont équivalents.

Le concept des syndicats est différent de celui des classes déclarées avec struct et class, car les syndicats ne peuvent stocker un membre de données à la fois, mais néanmoins ils sont aussi des classes et peuvent donc également tenir les membres de la fonction. L'accès par défaut dans les classes syndicaux est public. 
Publié par Drupal Study