Vous êtes sur la page 1sur 25

1

Les objets dynamiques


1- Cas d’une classe sans constructeur:
- nous déclarons :
point * adr ;
- créer dynamiquement un emplacement de type point(la place pour deux entiers)
adr = new point ;
class point
{ int x, y ;
public :
void initialise (int, int) ;
void deplace (int, int) ;
void affiche ( ) ;
};

- L’accès aux fonctions membres de l’objet pointé par adr:

- la suppression de l’objet :

2
2-Cas d’une classe avec constructeur
L’opérateur new appellera un constructeur de l’objet.
new puisse appeler un constructeur disposant d’arguments

Syntaxe:
new point (1, 2) ;
s’il n’existe pas de constructeur, ou s’il existe un constructeur sans argument.
Acceptées

new point ;//


new point () ;//
si tous les constructeurs possèdent au moins un argument, cette
syntaxe sera rejetée.

l’opérateur delete appellera le destructeur.

Exemple: Ecrire un programme qui permet de créer dynamiquement un objet de


type point dans la fonction main et qui le détruit dans une fonction fct (appelée
par main). Les messages affichés permettent de mettre en évidence les moments
auxquels sont appelés le constructeur et le destructeur. 3
#include <iostream>
using namespace std ;
class point
{ int x, y ;
public :
point (int abs, int ord) // constructeur
{ x=abs ; y=ord ;
cout << "++ Appel Constructeur \n" ;
}
~point
{ cout << "-- Appel Destructeur \n" ;
}
};
main()
{ void fct (point *) ;
point * adr ;
cout << "** Debut main \n" ;
adr = new point (1,2) ; // création dynamique d’un objet
fct (adr) ;
cout << "** Fin main \n" ;
}
void fct (point * adp)
{ cout << "** Debut fct \n" ;
delete adp ; // destruction de cet objet
cout << "** Fin fct \n" ; 4
}
LE CONSTRUCTEUR PAR COPIE

 Emploi du constructeur de recopie par défaut: lorsque aucun


constructeur de recopie n’a été défini
 Le constructeur par copie: prend en paramètre une référence vers
une instance de la classe.

o si le développeur n’en fournit pas, le compilateur en fournit un copie


membre à membre.

o Le constructeur par copie est appelé, lorsqu’une instance de classe :


 soit passée par valeur à une fonction et elle est retournée par une
fonction
 soit initialisée avec une autre instance/objet ( initialisation :
affectation à la déclaration)

5
Emploi du constructeur de recopie par défaut: lorsque aucun
constructeur de recopie n’a été défini.
Exemple: l’utilisation de la classe vecteur et de transmettre par valeur un
objet de type vect à une fonction nommée fct:
#include <iostream>
using namespace std ;
class vecteur
{ int n_element ; // nombre d’éléments
double * adr ; // pointeur sur ces éléments
public : void fct (vecteur b)
vecteur (int n) // constructeur "usuel" { cout << "*** appel de fct ***\n" ;
{ adr = new double [n_element = n] ; }
cout << "+ const. usuel - adr objet : " << this main()
<< " - adr vecteur : " << adr << "\n" ; { vecteur a(2) ;
} fct (a) ;
~vecteur () }
{ cout << "- Destr. objet - adr objet : "
<< this << " - adr vecteur : " << adr << "\n" ;
delete adr ;
}
}; 6
CONSTRUCTEUR DE COPIE
 On peut éviter ce problème en faisant en sorte que l’appel : fct (a) ;
conduise à créer « intégralement » un nouvel objet de type vect, avec ses
membres données (nelem et adr), mais aussi son propre emplacement de
stockage
Solution: Le constructeur de copie permet d’initialiser un objet en copiant les
attributs d’un autre objet du même type.

 Syntaxe :
NomClasse(NomClasse & autre) { ... }

 Exemple :

Rectangle(Rectangle & autre)

: hauteur(autre.hauteur), largeur(autre.largeur)
{}
7
Le constructeur par copie est appelé: passée par valeur à une fonction
#include <iostream>
using namespace std ;
class vecteur
{ int nelem ; // nombre d’éléments
double * adr ; // pointeur sur ces éléments
public :
vecteur (int n) // constructeur "usuel"
{ adr = new double [nelem = n] ;
cout << "+ const. usuel - adr objet : " << this<< " - adr vecteur : " << adr << "\n" ;}
vecteur (const vecteur & v) // constructeur de copie
{ adr = new double [nelem = v.nelem] ; // création nouvel objet
int i ; for (i=0 ; i<nelem ; i++) adr[i]=v.adr[i] ; // recopie de l’ancien
cout << "+ const. recopie - adr objet : " << this<< " - adr vecteur : " << adr << "\n" ;
}
~vect () // destructeur
{ cout << "- Destr. objet - adr objet :" << this << " - adr vecteur : " << adr << "\n" ;
delete adr ;
}
};
void fct (vecteur b)
{ cout << "*** appel de fct ***\n" ; }
main()
{ vecteur a(2) ; fct (a) ;// Le constructeur par copie est appelé: passée par valeur à une8
fonction
}
LE CONSTRUCTEUR DE COPIE
+ const. usuel - adr objet : 0X6AFDE4 - adr vecteur : 0X7D0320
+ const. recopie - adr objet : 0X6AFD88 - adr vecteur : 0X7D0100
*** appel de fct ***
- Destr. objet - adr objet : 0X6AFD88 - adr vecteur : 0X7D0100
- Destr. objet - adr objet : 0X6AFDE4 - adr vecteur : 0X7D0320

 Exemple de constructeur de copie: initialisation avec une autre


instance/objet ( initialisation : affectation à la déclaration)

Rectangle r1(12.5, 24.5);


Rectangle r2(r1);

r1 et r2 sont deux objets distincts mais ayant des mêmes valeurs pour leurs
attributs

9
#include <iostream>
using namespace std ;
class point
{ int x, y ;
public :
point (int abs=0, int ord=0) // constructeur "usuel"
{ x=abs ; y=ord ;
cout << "++ Appel Const. usuel " << this << " " << x << " " << y << "\n" ;
}
point (const point & p):x(p.x), y(p.y) // constructeur de recopie
//{ x=p.x ; y=p.y ;
{cout << "++ Appel Const. recopie " << this << " " << x << " " << y << "\n" ;
}
~point ()
{ cout << "-- Appel Destr. " << this << " " << x << " " << y << "\n" ;
}
point symetrique () ;
};
point point::symetrique ()
{ point res ; res.x = -x ; res.y = -y ; return res ;
}
main()
{ point a(1,3), b ;
cout << "** avant appel de symetrique\n" ;
b = a.symetrique () ;
point c(b);//
point c=b;//
10
cout << "** apres appel de symetrique\n" ;
}
Mise en œuvre des constructeurs et des destructeurs: Appel des
différents constructeurs dans le cas d’objets membres
Exemple: Soient les deux classes point et cercle
class point
{ int x, y ;
public :
point (int, int) ;
};
class cercle
{ point centre ;
int rayon ;
public :
cercle (int, int, int) ;
};
cercle::cercle (int abs, int ord, int ray) : centre (abs, ord)// l’en-tête de cercle spécifie,
après les deux-points, la liste des arguments qui seront transmis à point.
{ ...
}

11
#include <iostream>
using namespace std ;
class point
{ int x, y ;
public :
point (int abs=0, int ord=0)
{ x=abs ; y=ord ;
cout << "Constr. point " << x << " " << y << "\n" ;
}
};
class cercle
{ point centre ;
int rayon ;
public :
cercle (int , int , int) ;
};
cercle::cercle (int abs, int ord, int ray) : centre(abs, ord)
{ rayon = ray ;
cout << "Constr. cercle " << rayon << "\n" ;
}
main()
{cercle a (1,3,5) ;}
Constructeur: cercle::cercle (int abs, int ord, int ray)
{ rayon = ray ;
centre = point (abs, ord) ; 12
cout << "Constr. cercle " << rayon << "\n" ;
}
Les tableaux d’objets
En C++, un tableau peut posséder des éléments de n’importe quel type, y compris de
type objet: ce qui conduit alors à des tableaux d’objets
point courbe [10]//
for (i = 0 ; i < 10 ; i++) courbe[i].affiche() ;// Exemple:
using namespace std ;
class point
{ int x, y ;
public :
point (int abs=0, int ord=0)
{ x=abs ; y =ord ;
cout << "++ Constr. point : " << x << " " << y << "\n" ;
}
~point ()
{ cout << "-- Destr. point : " << x << " " << y << "\n" ;
}
};
main()
{ int n = 2 ;
point courbe[4] = {5, n, 2*n } ;
cout << "*** fin programme ***\n" ;
}

13
Cas des tableaux dynamiques d’objets
Pour créer dynamiquement un tableau de points en faisant appel à l’opérateur new:
Exemple :
point * courbe = new point[10] ;
Pour détruire notre tableau d’objets:
delete [] courbe
Les objets temporaires
Soit le constructeur :point (int, int) ;
Soit affectation telle que : a = point (1, 2) ;
point (1, 2)// la création d’un objet temporaire de type point
Rq: Quant à l’objet temporaire ainsi créé, il n’a plus d’intérêt dès que l’instruction
d’affectation est exécutée. La norme prévoit qu’il soit détruit dès que possible (qui se
trouve détruit tout de suite après).
main()
{ point a(0,0) ; //
a = point (1, 3) ; // 14

a = point (3, 4) ; //
cout << " Fin main \n" ;}
DÉVELOPPEMENT EN C++:
PROGRAMMATION ORIENTÉE OBJET
AVEC C++

15

AU 2019-2020
LES FONCTIONS AMIES
Le principe d'encapsulation fait qu'une classe interdit à ses
utilisateurs externes l'accès à ses membres privés

Parfois, une telle protection peut être contraignante comme pour


l'exemple suivant : On suppose qu'on dispose de 2 classes Matrice et
Vecteur. On cherche à définir une méthode qui calcule le produit
d'une matrice et d'un vecteur.

En appliquant le principe d'encapsulation d’une façon stricte, il ne


serait possible de définir cette fonction ni comme étant membre de
la classe Matrice, ni comme membre de la classe Vecteur ni encore
16

comme une fonction indépendante.


INTRODUCTION

Comme solution à ce problème il est possible de :


Déclarer les attributs comme publiques chose qui engendre en
contre partie la perte du bénéfice de leur protection.

17
SOLUTION
 Le C++ dispose d'un outil qui permet de contourner l'encapsulation dans
certaines circonstances et pour certaines fonctions.

Cet outil est


celui des
fonctions
amies..

18
LA NOTION D'AMITIÉ
• L'amitié peut être entre une fonction et une classe ou même entre deux
classes.

o Une fonction amie d'une classe est autorisée à accéder aux membres
privés comme n'importe quel autre membre de cette classe.

O Les méthodes d'une classe X amie d'une classe Y sont autorisées à


accéder à tous les membres privés de cette classe Y.

• La notion d'amitié est déclarée par le mot-clé friend.

Il existe plusieurs situations d’amitié:

- Une fonction indépendante est amie d’une ou plusieurs classes.


- Une ou plusieurs fonctions membres d’une classe donnée sont amies
d’une autre classe. 19
FONCTION AMIE D'UNE CLASSE
 Une fonction peut être définie comme étant amie d'une classe.

 Cette fonction peut être indépendante ou membre d'une autre classe.

 Fonction indépendante amie d'une classe

 La déclaration d'une fonction F comme amie d'une classe A se fait à


l'intérieur de cette dernière comme suit:
class A
{
………
friend TypeRetour F(Liste des paramètres);
………
};

20
FONCTION AMIE D'UNE CLASSE

 L'emplacement de la déclaration de l'amitié de F au sein de la


classe A peut se faire n'importe où dans cette dernière.

 D'ailleurs cet emplacement peut figurer indifféremment dans la


partie publique ou privée de la classe.

 Exemple :

Dans l’exemple ci-dessous, la fonction coïncide est AMIE de la


classe point. C’est une fonction ordinaire qui peut manipuler les
membres privés de la classe point.

21
EXEMPLE
//fonction indépendante, amie d'une int main()
classe {point a(4,0),b(4,0),c(1,3);
#include <iostream.h> if(coincide(a,b))cout<<"a coincide
using namespace std; avec b\n";
class point else cout<<"a est different de b\n";
{ if(coincide(a,c))cout<<"a coincide
private: avec c\n";
int x,y; else cout<<"a est different de c\n";
public: system("pause");
point(int abs=0,int ord=0){x=abs;y=ord;} return 0 ;}
//declaration de la fonction amie
friend int coincide(point,point);
};
int coincide(point p,point q)
{if((p.x==q.x)&&(p.y==q.y)) 22
return 1;
else return 0;}
FONCTION MEMBRE AMIE D'UNE CLASSE
 La fonction amie d'une classe peut ne pas être indépendante mais
plutôt une fonction membre d'une autre classe.

 Dans ce cas la déclaration de l'amitié se fait comme suit:


class B
{
………
TypeRetour F(Liste des paramètres);
………
};

class A
{
………
friend TypeRetour B::F(Liste des paramètres);
………
}; 23
FONCTION AMIE DE PLUSIEURS CLASSES
-Une fonction peut avoir besoin d'accéder aux membres privés de plusieurs classes et
nécessite par conséquent d'être déclarée amie de toutes ces classes en même temps.

-La déclaration d'amitié doit se faire dans ce cas dans toutes ces classes.

Exemple : On considère une fonction indépendante F qui doit accéder aux membres
privés de deux classes A et B. Le prototype de F est le suivant : void F(A, B); F doit
être déclarée amie à la fois à A et B : class B;
class A// Définition de A
{………
friend void F(A, B);
………
};
Syntaxe : class B // Définition de B
{………
friend void F(A, B);
………
};
void F(A a, B b) 24
{
… … …}
CLASSE AMIE D'UNE AUTRE CLASSE
 Ce cas de figure est une généralisation de l'amitié d'une fonction membre à
une classe.

 Il s'agit de déclarer toutes les fonctions d'une classe A comme amies aux
fonctions membres d'une autre classe B.

 Mais, le C++ offre une alternative qui consiste à effectuer une déclaration
d'amitié globale entre les classes. Ainsi, il suffit de déclarer la classe A comme
étant amie de la classe B.

class A
{
… … …};
 Syntaxe : class B
{
………
friend class A;
… … …}; 25
Dans ce cas, toutes les méthodes de A seront ainsi amies de B.

Vous aimerez peut-être aussi