Vous êtes sur la page 1sur 33

Ecole Marocaine des Sciences de l’Ingénieur

Marrakech

Propriétés des fonctions


membres
Plan du chapitre

1. Surdéfinition des méthodes membres


2. Les arguments par défaut d'une fonction membre
3. Autoréférence : le mot clé "this"
4. Les méthodes membres statiques
5. Les accesseurs et les mutateurs
6. Le constructeur de recopie

2
Sur définition des méthodes membres
▪ La surdefinition (surcharge) des fonctions s’applique également aux fonctions
membres d’une classe, y compris au constructeur (mais pas au destructeur
puisqu’il ne possède pas d’arguments).
1. Exemple

• Le constructeur point, le choix du bon constructeur se faisant ici suivant le nombre d’arguments :
• 0 argument : les deux coordonnées attribuées au point construit sont toutes deux nulles,
• 1 argument : il sert de valeur commune aux deux coordonnées,
• 2 arguments : c'est le cas "usuel" que nous avions déjà rencontré.
• La fonction affiche de manière qu'on puisse l'appeler :
• sans argument comme auparavant,
• avec un argument de type chaîne : dans ce cas, elle affiche le texte correspondant avant les
coordonnées du point.

void point::affiche (char * message) { cout << message ; affiche () ;}

3
Sur définition des méthodes membres
1. Exemple (suite)
class point point::point () // constructeur 1
{ int x, y ; {x=0;y=0;
public : }
point () ; // constructeur 1 (sans arguments) point::point (int abs) // constructeur 2
point (int) ; // constructeur 2 (un argument) { x = y = abs ;
point (int, int) ; // constructeur 3 (deux arguments) }
void affiche () ; // fonction affiche 1 (sans arguments) point::point (int abs, int ord) // constructeur 3
void affiche (char *) ; // fonction affiche 2 (un argument { x = abs ; y = ord ;
chaîne) }
}; void point::affiche () // fonction affiche 1
{ cout << "Je suis en : " << x << " " << y << "\n" ;
}
Classe point void point::affiche (char * message) // fonction affiche 2
Définition des méthodes { cout << message ; affiche () ;
}

int main(void)
{
point p; p.affiche(); p.affiche("Bonjour a tous"); cout<<"\n";
point q(3); q.affiche(); q.affiche("Salamo alikoum"); cout<<"\n";
point r(3,2); r.affiche(); r.affiche("Salut"); cout<<"\n";
}
4
Sur définition des méthodes membres
1. Exemple (suite)

main()
{ point a ; // appel constructeur 1
a.affiche () ; // appel fonction affiche 1
point b (5) ; // appel constructeur 2
b.affiche ("Point b - ") ; // appel fonction affiche 2
point c (3, 12) ; // appel constructeur 3
c.affiche ("Hello ---- ") ; // appel fonction affiche 2
}

Fonction main

5
Sur définition des méthodes membres

▪ Exercice

Ecrire une classe "Calculateur" qui a comme méthode, un constructeur par défaut et les quatre opérations de calcul
surchargées pour les types de données double, float, et entier.

6
Sur définition des méthodes membres

▪ Remarques

▪ Dans l'exemple précèdent la méthode affiche(char *) fait appel à la méthode affiche().


▪ En effet, une fonction membre peut toujours en appeler une autre (qu'elle soit publique ou non).

7
Arguments par défaut
Comme les fonctions ordinaires, les fonctions membres peuvent disposer d’arguments par défaut. Voici comment
nous pourrions modifier l'exemple de notre classe point pour qu'elle ne possède plus qu'une seule fonction affiche
disposant d’un seul argument de type chaîne. Celui-ci indique le message à afficher avant les valeurs des
coordonnées et sa valeur par défaut est la chaîne vide.

▪ Exemple

class point
{
int x, y ;
public :
point () ; // constructeur 1 (sans argument)
point (int) ; // constructeur 2 (un argument)
point (int, int) ; // constructeur 3 (deux arguments)
void affiche (string message=" "); // fonction affiche (un argument par
défaut)
};

9
Arguments par défaut
▪ Exemple (suite)

point::point () // constructeur 1 main()


{x=0;y=0; {
} point a ; // appel constructeur 1
point::point (int abs) // constructeur 2 a.affiche () ;
{ x = y = abs ; point b (5) ; // appel constructeur 2
} b.affiche ("Point b - ") ;
point::point (int abs, int ord) // constructeur 3 point c (3, 12) ; // appel constructeur 3
{ x = abs ; y = ord ; c.affiche ("Hello ---- ") ;
} }
void point::affiche (char * message) // fonction affiche
{ cout << message << "Je suis en : " << x << " " << y << "\n" ; Je suis en : 0 0
} Point b - Je suis en : 5 5
Hello ---- Je suis en : 3 12

10
Autoréférence : le pointeur "this"
1. Définition

• Dans toutes les classes, on dispose d'un pointeur ayant pour nom this, qui pointe vers l'objet actuel.
• À chaque appel d'une fonction membre, le compilateur passe implicitement en paramètre un pointeur sur les
données de l'objet.
• Le pointeur this est accessible seulement à l'intérieur des fonctions membres

• this étant utilisé par le langage C++ dans toutes les classes, vous ne
pouvez pas créer de variable appelée this car cela susciterait un conflit.
De même, si vous commencez à essayer d'appeler vos variables class,
new, delete, return, etc. vous aurez un problème.

• Ces mots-clés sont ce qu'on appelle des « mots-clés réservés ». Le


langage C++ les réserve pour son usage personnel, vous n'avez donc
pas le droit de créer des variables (ou des fonctions) portant ces noms-là.

11
Autoréférence : le pointeur "this"
2. Exemple

class Personne{
char nom[20];
int age;
public :
int getAge();
};
// la fonction age retourne l'age de l'objet en cours d'utilisation
int Personne:: getAge(){
return this->age;
}

12
#include<iostream>
using namespace std;

class point{

int x, y;
public :
point(int abs=0,int ord=0 ) //constructeur (inline)
{
x=abs; y=ord;
}
void affiche() ;

};

void point::affiche(){

cout << "adresse : " << this<<" coordonnees "<<x << " " << y << endl;
}

int main()
{

point a(5), b(3,15);


a.affiche();
b.affiche();

system("PAUSE") ;
return 0; 13

}
Autoréférence : le pointeur "this"
3. à quoi peut bien servir this ?

vous êtes dans une méthode de votre classe et cette méthode doit renvoyer un pointeur vers l'objet auquel elle
appartient. Sans le this, on ne pourrait pas l'écrire. Voilà ce que cela pourrait donner :

Personne* Personne::getAdresse() {
return this;
}

• this étant un pointeur sur un objet


• *this est l'objet lui-même

14
Les méthode membres statiques
1. Définition

• Les méthodes dites statiques sont des méthodes de classes précédées par le mot clé static (de la même manière
que les variables statiques).
• Elle ne peuvent faire des traitement que sur des variables statiques
• On peut les appeler sans avoir une instance  syntaxe : nom_de_classe::nom_fonction_statique()
• Elle ne peuvent pas êtres surchargées

2. Exemple

class Personne{
static int nbrInstance;
static int nbrInstance(){return nbrInstance; } // méthode statique
}
int Personne::nbrInstance = 0;

15
Les méthode membres statiques
2. Exemple (suite)

Appel de la méthode statique

main(){
cout << "le nombre de personne vivant est : " << Personne::nbrInstance() << endl; // affiche 0
Personne p1,p2;
cout << "le nombre de personne vivant est : " << Personne::nbrInstance() << endl; // affiche 2
}

16
Les accesseurs et les mutateurs
1. La protection des données membres

▪ L'un des aspects les plus essentiels du concept « orienté objet » est l'encapsulation, qui consiste à définir des
étiquettes pour les données membres et les fonctions membres afin de préciser si celles-ci sont accessibles à
partir d'autres classes ou non...

▪ De cette manière, des données membres portant l'étiquette private ne peuvent pas être manipulées
directement par les fonctions membres des autres classes. Ainsi, pour pouvoir manipuler ces données
membres, le créateur de la classe (vous en l'occurrence) doit prévoir des fonctions membres spéciales portant
l'étiquette public, permettant de manipuler ces données.

• Les fonctions membres permettant d'accéder aux données membres sont appelées accesseurs,
parfois getter (appellation d'origine anglophone)
• Les fonctions membres permettant de modifier les données membres sont appelées mutateurs,
parfois setter (appellation d'origine anglophone)

17
Les accesseurs et les mutateurs
2. La notion d'accesseur

▪ Un accesseur est une fonction membre permettant de récupérer le contenu d'une donnée
membre protégée. Un accesseur, pour accomplir sa fonction :
▪ doit avoir comme type de retour le type de la variable à renvoyer
▪ ne doit pas nécessairement posséder d'arguments
▪ Une convention de nommage veut que l'on fasse commencer de façon préférentielle le nom de l'accesseur
par le préfixe Get, afin de faire ressortir sa fonction première.
Syntaxe:

class MaClasse{
private : typeDeMaVariable MaVariable;
public : typeDeMaVariable GetMaVariable();
};
typeDeMaVariable MaClasse::GetMaVariable(){
return MaVariable;
}

18
Les accesseurs et les mutateurs
2. La notion d'accesseur

▪ Un accesseur est une fonction membre permettant de récupérer le contenu d'une donnée
membre protégée. Un accesseur, pour accomplir sa fonction :
▪ doit avoir comme type de retour le type de la variable à renvoyer
▪ ne doit pas nécessairement posséder d'arguments
▪ Une convention de nommage veut que l'on fasse commencer de façon préférentielle le nom de l'accesseur
par le préfixe Get, afin de faire ressortir sa fonction première.
Syntaxe: Exemple
class MaClasse{ class Personne{
private : typeDeMaVariable MaVariable; private : int age;
public : typeDeMaVariable GetMaVariable(); public : int Getage();
}; };
typeDeMaVariable MaClasse::GetMaVariable(){ Int Personne ::Getage(){
return MaVariable; return age;
} }

19
Les accesseurs et les mutateurs
3. La notion de mutateur
▪ Un mutateur est une fonction membre permettant de modifier le contenu d'une donnée membre
protégée. Un mutateur, pour accomplir sa fonction :
▪ doit avoir comme paramètre la valeur à assigner à la donnée membre. Le paramètre doit donc être du type
de la donnée membre
▪ ne doit pas nécessairement renvoyer de valeur (il possède dans sa plus simple expression le type void)
▪ Une convention de nommage veut que l'on fasse commencer de façon préférentielle le nom du
mutateur par le préfixe Set.
Syntaxe: Exemple
class MaClasse{ class Personne{
private : typeDeMaVariable MaVariable; private : int age;
public : void setMaVariable(typeDeMaVariable ); public : void setage(int);
}; };
void MaClasse::setMaVariable(typeDeMaVariable variable){ void Personne::setMaVariable(int variable){
MaVariable = variable; MaVariable = variable;
} }

20
Constructeur de recopie
1. Définition

• Le constructeur de copie est une surcharge particulière du constructeur.

• De la même manière que l'affectation (par défaut), le constructeur de recopie par défaut effectue la copie membre
à membre de la source vers la destination.

▪ Il est appelé dans trois situations

Retour de fonction par


Initialisation d'un objet Paramètre passé par valeur
valeur
• Création d'un nouvel objet • Un objet transmit à une • Une fonction qui retourne
initialisé comme étant une fonction par valeur un objet
copie d'un objet existant
Ne pas confondre initialisation et • Ou bien initialiser un objet
affectation à partir d'un autre déjà
créé

21
Qu’est-ce qu’un constructeur de copie?

▪ Un constructeur de copie est une fonction membre qui initialise un objet en


utilisant un autre objet de la même classe. Un constructeur de copie a le
prototype suivant:
▪ ClassName (const ClassName &obj);
▪ Ici, obj est la référence d’un objet utilisé pour initialiser un autre objet
▪ Const C++
▪ En programmation dans les langages C ou C++, const est un mot-clé permettant au
programmeur de signaler au compilateur que l'élément ainsi qualifié ne doit pas être modifié
pendant l'exécution du programme. Cet élément sera donc constant tout le long d'une
exécution normale du programme

22
Constructeur de recopie
Admettons qu'on dispose d'une classe Date qui à comme attributs 3 pointeurs *jour, *mois
et *annee, pour la partie méthodes on se dispose d'un constructeur avec les trois
paramètres, un destructeur qui libère la mémoire allouée par le constructeur.

class Date{
int *jour, *mois, *annee;
public: main(){
Date(int j, int m, int a){ Date d1(1,1,2001);
jour = new int; *jour =j; Date d2 = d1;
mois = new int; *mois = m; d2.affiche();
annee = new int; *annee = a; }
}
~Date(){
delete jour;
delete mois;
delete annee; Qu'est ce qui se passe en réalité ?
cout<<"\n objet detruit"<<endl;
}
void affiche(){cout<<"jour="<<*jour<<" "<<"mois="<<*mois<<"
"<<"annee"<<*annee<<endl;}
}; 23
Constructeur de recopie
2. un constructeur de copie
▪ Règles
▪ Un constructeur de copie porte le même nom que la classe
▪ Ne retourne rien même pas void
▪ Il a comme paramètre un objet de la même classe
▪ Syntaxe (prototype)

nomDeLaClasse ( const nomDeLaClasse & )

▪ Exemple Date(const Date & d2) {


jour = new int;
mois = new int;
annee = new int;
*jour = *(d2.jour);
*mois = *(d2.mois);
*annee = *(d2.annee);
}
24
#include <iostream>
using namespace std;

class Date {
int *jour, *mois, *annee;

public:
Date(int j, int m, int a) {
jour = new int; mois = new int; annee = new int;
*jour = j; *mois = m; *annee = a;
}

Date(const Date & d2) {


jour = new int;
mois = new int;
annee = new int;
*jour = *(d2.jour);
*mois = *(d2.mois);
*annee = *(d2.annee);
}

~Date() {
delete jour;
delete mois;
delete annee;
cout << "\nobjet detruit" << endl;
}

void affiche() {
cout << "jour=" << *jour << " " << "mois=" << *mois << " " <<
"annee=" << *annee << endl;
}
};

int main() {
Date d1(1, 1, 2001);
Date d2(d1);
d2.affiche();

return 0;
} 25
#include <iostream>
#include <stdlib.h>
using namespace std;
class Date{
int jour, mois, annee;
public:
Date(int j, int m, int a){

this->jour =j;
this->mois = m;
this->annee = a;
}
Date( const Date& d ){
jour =d.jour;
mois = d.mois;
annee = d.annee;
}
void affiche(){cout<<"jour="<<jour<<" "<<"mois="<<mois<<"
"<<"annee"<<annee<<endl;}
};

main(){
Date d1(1,1,2001);
Date d2(d1);
d2.affiche();
}

26
#include<iostream>
using namespace std;
class Point{
private:
int x, y;
public:
Point(int x1, int y1) { x = x1; y = y1; }
/* Constructeur de copie */
Point (const Point &p) {
x = p.x; y = p.y;
}
void afficher() {
cout << x << " " << y << endl;
}
};
int main(){
Point obj1(3, 7); // Constructeur paramétré
Point obj2 = obj1; // Constructeur de copie
cout <<" Constructeur paramétré : ";
obj1.afficher();
cout <<" Constructeur de copie : ";
obj2.afficher();
return 0;
}

27
Dans le cas ci-dessus, le constructeur de copie peut être appelé de la manière suivante:

Quand le constructeur de copie est appelé?


Le constructeur de copie est appelé dans les scénarios suivants:
1. Lorsque nous initialisons l’objet avec un autre objet existant du même type de classe. Par exemple, Point p1 = p2, où Point est la classe de base.
2. Lorsque l’objet du même type de classe est passé par valeur en tant qu’argument==Point R(p)
3. Lorsque la fonction retourne l’objet du même type de classe= Point T= R.fonc().

28
#include<iostream>
using namespace std;
class Point{
private:
int x, y;
public:
Point(int, int);
Point (const Point &);
void afficher();
Point fonc(){return *this;}
};
Point::Point(int x1, int y1) { this->x = x1; this->y = y1; }
Point:: Point (const Point &p) { this->x = p.x; this->y = p.y; }

void Point::afficher() { cout << x << " " << y << endl;}
int main(){
Point p(3, 7); // Constructeur paramétré
Point q = p; // Constructeur de copie
Point R(q);
Point T= R.fonc();
cout <<" Constructeur paramétré : ";
p.afficher();
cout <<" Constructeur de copie : ";
q.afficher();
R.afficher();
T.afficher();
return 0;
}
29
Exercices

Refaire l'exemple de la classe point avec des mutateurs et des accesseurs et un constructeur de recopie

Ajouter une méthode "coïncide (Point p)" à la classe point qui return true si le point passé en paramètre coïncide
avec le point en cours, false si non. (utiliser le pointeur this)

30
#include <iostream>
using namespace std;
class point { int main() {
int x, y; point p, q(2, 3), t(3);
public:
point(int x = 2, int y = 3) { bool t1, t2;
this->x = x; t1 = p.coincide(q);
this->y = y; t2 = p.coincide(t);
}
point(const point& p) {
this->x = p.x; cout << "p.coincide(q)--> " << t1 << endl;
this->y = p.y; cout << "p.coincide(t)--> " << t2 << endl;
}

int getX() { return 0;


return x; }
}
void setX(int a) {
x = a;
}
int getY() {
return y;
}
void setY(int b) {
y = b;
}
bool coincide(point p) {
return (x == p.x && y == p.y);
}
}; 31
Corrigé de l’exercice 1
#include<iostream>
using namespace std;
class Point{
private:
int x, y;
public:
Point(int x1, int y1){ x = x1; y = y1; }
/* Constructeur de copie */
Point (const Point &p) {
x = p.x; y = p.y;
}
//Accesseur: getter
int getX() {return x;}
int getY() {return y;}
// mutateurs: setter
void setX(int a){x=a;}
void setY(int b){y=b;}

void afficher() {
cout << "x= "<<x<<" "<<"y=" <<" "<<y<< endl; }
void afficher(Point &p) {
cout <<"objet.getX()="<<p.getX()<< " " << "objet.getX()="<<" "<<p.getY() << endl;
}
};
int main(){
Point obj1(3, 7); // Constructeur paramétré
Point obj2 = obj1; // Constructeur de copie
cout <<" Constructeur parametre : \t";
obj1.afficher();
cout <<" Constructeur de copie : \t";
obj2.afficher();
Point obj3(4, 8);
obj1.afficher(obj3);
obj3.setX(5);
obj3.setY(7);
obj3.afficher();
return 0;
}

32
Corrigé de l’exercice 2
#include <iostream>
#include <conio.h>
using namespace std;class point {
int x,y;
public:
point(int abs = 0,int ord = 2){x=abs;y=ord;}
bool coincide(point pt) {
if ((pt.x == x) && (pt.y == y))
return(true);
else
return(false);
}
//ou bien
bool coincide(point pt) {
return ((pt.x == x) && (pt.y == y))
}
};
main() {
bool test1,test2;
point a,b(1),c(0,2);
test1 = a.coincide(b);
test2 = b.coincide(a);
cout<<"a et b:"<<test1<<" ou "<<test2<<"\n";
test1 = a.coincide(c);
test2 = c.coincide(a);
cout<<"a et c:"<<test1<<" ou "<<test2<<"\n";
getch() ;
} 33
#include<iostream>
using namespace std;
class Point{
private:
int x, y;
public:
Point(int x1=2, int y1=3){x = x1; y = y1; }
Point (const Point &p) { x = p.x; y = p.y;}
//Accesseur: getter
int getX() {return x;}
int getY() {return y;}
// mutateurs: setter
void setX(int a){x=a;}
void setY(int b){y=b;}

void afficher() { cout << "x= "<<x<<" "<<"y=" <<" "<<y<< endl; }
void afficher(Point p) {
cout <<"objet.getX()="<<p.getX()<< " " << "objet.getX()="<<" "<<p.getY() << endl;
}
bool coincide(Point pt) {
if ((pt.x == x) && (pt.y == y))
return(true);
else
return(false);
}
/*ou bien
bool coincide(point pt) {
return ((pt.x == x) && (pt.y == y))
}
*/

};
int main(){

bool test1,test2;
Point a,b(1),c(2,3);
test1 = a.coincide(b);
test2 = b.coincide(a);
cout<<"a et b:"<<test1<<" ou "<<test2<<"\n";
test1 = a.coincide(c);
test2 = c.coincide(a);
cout<<"a et c:"<<test1<<" ou "<<test2<<"\n";
//-----------------------------------
a.afficher(b);
b.afficher(c);
a.setX(3);
a.setY(6);
cout<<"a.x="<<" "<<a.getX()<<" "<<"a.y="<<" "<<a.getY()<<endl;

return 0;
}

34

Vous aimerez peut-être aussi