'>

Amitié et l'héritage en C-Plus-Plus

 fonctions ami
En principe, les membres privés et protégés d'une classe ne sont pas accessibles de l'extérieur de la même classe dans laquelle ils sont déclarés. Toutefois, cette règle n'a pas d'incidence amis.

Les amis sont des fonctions ou des classes déclarées avec l' friend -clé.

Si nous voulons déclarer une fonction externe comme ami d'une classe, permettant ainsi à cette fonction pour avoir accès aux membres privés et protégés de cette classe, nous le faisons en déclarant un prototype de cette fonction externe dans la classe, et précéder le mot-clé ami:

 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


  

 // friend functions #include <iostream> using namespace std; class CRectangle { int width, height; public : void set_values ( int , int ); int area () { return (width * height);} friend CRectangle duplicate (CRectangle); }; void CRectangle::set_values ( int a, int b) { width = a; height = b; } CRectangle duplicate (CRectangle rectparam) { CRectangle rectres; rectres.width = rectparam.width*2; rectres.height = rectparam.height*2; return (rectres); } int main () { CRectangle rect, rectb; rect.set_values (2,3); rectb = duplicate (rect); cout << rectb.area(); return 0; }

  

  24



La fonction de copie est un ami de CRectangle. De l'intérieur de cette fonction, nous avons été en mesure d'accéder à la largeur et la hauteur de membres différents objets de type CRectangle, qui sont membres privés. Notez que ni dans la déclaration de duplicate () ni dans son utilisation ultérieure dans main () Avons-nous envisagé dupliquer un membre de CRectangle de classe. Il ne s'agit pas! Il a simplement accès à ses membres privés et protégés sans être membre.

L'ami fonctions peuvent servir, par exemple, de mener des opérations entre deux classes différentes. En règle générale, l'utilisation des fonctions friend est sur une méthodologie de programmation orientée objet, de sorte que chaque fois que possible, il est préférable d'utiliser des membres de la même classe pour effectuer des opérations avec eux. Comme dans l'exemple précédent, il aurait été plus courte pour intégrer duplicate () dans le CRectangle de classe.

classes ami
Tout comme nous avons la possibilité de définir une fonction amie, nous pouvons également définir une classe comme ami de l'autre, l'octroi de ce premier accès de classe pour les membres privés et protégés de la seconde.

 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
 35
 36


  

 // friend class #include <iostream> using namespace std; class CSquare; class CRectangle { int width, height; public : int area () { return (width * height);} void convert (CSquare a); }; class CSquare { private : int side; public : void set_side ( int a) {side=a;} friend class CRectangle; }; void CRectangle::convert (CSquare a) { width = a.side; height = a.side; } int main () { CSquare sqr; CRectangle rect; sqr.set_side(4); rect.convert(sqr); cout << rect.area(); return 0; }

  

  16



Dans cet exemple, nous avons déclaré CRectangle comme un ami de CSquare sorte que les fonctions de membre de CRectangle pourraient avoir accès aux membres privés et protégés de CSquare, plus concrètement à CSquare :: côté, qui décrit la largeur du côté de la place.

Vous pouvez également voir quelque chose de nouveau au début du programme: une déclaration vide de la classe CSquare. Cela est nécessaire parce que dans la déclaration de CRectangle nous nous référons à CSquare (comme paramètre dans convert ()). La définition de CSquare est inclus plus tard, si nous n'avons pas inclus une déclaration vide précédent pour CSquare cette classe ne serait pas visible à partir de la définition de CRectangle.

Considérer que l'amitié ne sont pas correspondu si nous ne spécifions pas explicitement. Dans notre exemple, CRectangle est considéré comme un ami par classe CSquare, mais CRectangle ne considère pas CSquare d'être un ami, alors CRectangle peut accéder aux membres privés et protégés de CSquare mais pas la façon inverse. Bien sûr, nous aurions pu également déclaré CSquare comme ami de CRectangle si nous le voulions.

Une autre propriété de l'amitié, c'est qu'ils ne sont pas transitive: L'ami d'un ami n'est pas considéré comme un ami, sauf indication explicite.

Héritage entre les classes
Une caractéristique clé de classes C + + est l'héritage. L'héritage permet de créer des classes qui dérivent des autres classes, afin qu'ils comprennent automatiquement certains des membres de son "des parents", plus propre. Par exemple, nous allons supposer que nous voulons déclarer une série de classes qui décrivent les polygones comme notre CRectangle, ou comme CTriangle. Ils ont certaines propriétés communes, telles que les deux peuvent être décrits au moyen de seulement deux côtés: hauteur et la base.

Cela pourrait être représentée dans le monde des classes avec un CPolygon de classe à partir de laquelle nous pourrions tirer les deux autres: CRectangle et CTriangle.


Le CPolygon de classe devrait contenir membres qui sont communs aux deux types de polygone. Dans notre cas: largeur et hauteur. Et CRectangle et CTriangle seraient ses classes dérivées, avec d'autres caractéristiques qui sont différentes d'un type de polygone à l'autre.

Les classes qui dérivent des autres héritent de tous les membres accessibles de la classe de base. Cela signifie que si une classe de base comprend un élément A et nous dérivons vers une autre classe avec un autre membre appelé B, la classe dérivée contiendra deux membres A et B.

Afin de dériver une classe d'une autre, nous utilisons deux points (:) dans la déclaration de la classe dérivée en utilisant le format suivant:

derived_class_name de classe: base_class_name publique
{/ * ... * /};

Où derived_class_name est le nom de la classe dérivée et base_class_name est le nom de la classe sur laquelle il est basé. Le spécificateur d'accès public peut être remplacé par l'un quelconque des autres prescripteurs d'accès protégés et privés. Ce spécificateur d'accès limite le niveau le plus accessible pour les membres hérités de la classe de base: Les membres ayant un niveau plus accessible sont héritées à ce niveau au lieu, tandis que les membres ayant un niveau d'accès égale ou plus restrictive gardent leur niveau restrictive dans la classe dérivé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
 31
 32
 33


  

 // derived classes #include <iostream> using namespace std; class CPolygon { protected : int width, height; public : void set_values ( int a, int b) { width=a; height=b;} }; class CRectangle: public CPolygon { public : int area () { return (width * height); } }; class CTriangle: public CPolygon { public : int area () { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; rect.set_values (4,5); trgl.set_values (4,5); cout << rect.area() << endl; cout << trgl.area() << endl; return 0; }

  

  20
  10



Les objets de la classe CRectangle et CTriangle contiennent chacun des membres hérités de CPolygon. Ce sont: largeur, hauteur et set_values ​​().

Le spécificateur d'accès protégé est similaire au privé. Sa seule différence se produit en fait avec l'héritage. Quand une classe hérite d'une autre, les membres de la classe dérivée peuvent accéder aux membres protégés hérités de la classe de base, mais pas à ses membres privés.

Comme nous voulions largeur et la hauteur pour être accessible à partir de membres de la classe dérivée CRectangle et CTriangle et pas seulement par les membres de CPolygon, nous avons utilisé l'accès au lieu de privé protégé.

Nous pouvons résumer les différents types d'accès selon qui peuvent y accéder de la façon suivante:

Accès     publique     protégé     privé
les membres de la même classe     oui     oui     oui
les membres des classes dérivées     oui     oui     pas
non membres     oui     pas     pas

Où "non membres" représentent tout accès de l'extérieur de la classe, comme de main (), d'une autre classe ou d'une fonction.

Dans notre exemple, les membres hérités par CRectangle et CTriangle avoir les mêmes droits d'accès comme ils l'avaient dans leur CPolygon classe de base:

 1
 2
 3
 4
 5


  

 CPolygon::width // protected access CRectangle::width // protected access CPolygon::set_values() // public access CRectangle::set_values() // public access



C'est parce que nous avons utilisé le mot-clé public pour définir la relation d'héritage sur chacune des classes dérivées:



  

 class CRectangle: public CPolygon { ... }



Ce mot clé publique après les deux points (:) représente le niveau le plus accessible aux membres hérités de la classe qui le suit (dans ce cas CPolygon) auront. Depuis publique est le niveau le plus accessible, en spécifiant ce mot la classe dérivée héritera de tous les membres avec les mêmes niveaux qu'ils avaient dans la classe de base.

Si nous spécifions un niveau d'accès plus restrictives comme protégé, tous les membres publics de la classe de base sont hérités comme protégé dans la classe dérivée. Alors que si nous précisons les plus contraignantes de tous les niveaux d'accès: privé, tous les membres de la classe de base sont hérités comme privé.

Par exemple, si la fille était une classe dérivée de la mère que nous avons défini comme:



  

 class daughter: protected mother;



Cela créerait protégé que le niveau maximum d'accès pour les membres de sa fille dont il avait hérité de la mère. Autrement dit, tous les membres qui étaient publiques en mère deviendraient protégé en fille. Bien sûr, ce ne serait pas restreindre fille de déclarer ses propres membres publics. Ce niveau d'accès maximum est définie uniquement pour les membres hérités de la mère.

Si nous ne spécifions pas explicitement le niveau d'accès pour l'héritage, le compilateur suppose privé pour les classes déclarées avec le mot clé de classe et du public pour ceux qui sont déclarés avec struct.

Quel est héritée de la classe de base?
En principe, une classe dérivée hérite de tous les membres d'une classe de base, sauf:

    son constructeur et le destructeur
    son opérateur = () membres
    ses amis


Bien que les constructeurs et les destructeurs de la classe de base ne sont pas eux-mêmes hérité, son constructeur par défaut (ie, son constructeur sans paramètres) et le destructeur sont toujours appelés lorsqu'un nouvel objet d'une classe dérivée est créée ou détruite.

Si la classe de base n'a pas de constructeur par défaut ou si vous souhaitez qu'un constructeur surchargé est appelée quand un nouvel objet dérivé est créé, vous pouvez le spécifier dans la définition de chaque constructeur de la classe dérivée:

derived_constructor_name (paramètres): base_constructor_name (paramètres) {...}

Par exemple:

 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


  

 // constructors and derived classes #include <iostream> using namespace std; class mother { public : mother () { cout << "mother: no parameters\n" ; } mother ( int a) { cout << "mother: int parameter\n" ; } }; class daughter : public mother { public : daughter ( int a) { cout << "daughter: int parameter\n\n" ; } }; class son : public mother { public : son ( int a) : mother (a) { cout << "son: int parameter\n\n" ; } }; int main () { daughter cynthia (0); son daniel(0); return 0; }

  

  mère: pas de paramètres
  fille: int paramètre

  mère: paramètre int
  fils: paramètre int



Notez la différence entre ce qui constructeur de la mère est appelée quand un nouvel objet fille est créé et qui quand il est un objet fils. La différence, c'est parce que la déclaration de constructeur de fille et son fils:

 1
 2


  

 daughter ( int a) // nothing specified: call default son ( int a) : mother (a) // constructor specified: call this



L'héritage multiple
En C + +, il est parfaitement possible qu'une classe hérite des membres de plus d'une classe. Cela se fait simplement en séparant les différentes classes de base avec des virgules dans la déclaration de la classe dérivée. Par exemple, si nous avions une classe spécifique pour imprimer sur l'écran (COutput) et nous voulions que nos cours CRectangle et CTriangle d'hériter également à ses membres, en plus de ceux de CPolygon nous pourrions écrire:

 1
 2


  

 class CRectangle: public CPolygon, public COutput; class CTriangle: public CPolygon, public COutput;



Voici l'exemple complet:

 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
 35
 36
 37
 38
 39
 40
 41
 42


  

 // multiple inheritance #incl
Publié par Drupal Study