Programmation Orientée objet et C++ - LEM3 Orientee objet et...Programmation Orientée Objet et C++...

Post on 12-Jul-2020

24 views 1 download

Transcript of Programmation Orientée objet et C++ - LEM3 Orientee objet et...Programmation Orientée Objet et C++...

Programmation Orientée Objet et C++

Christophe Collard

Christophe Collard

Plan

Notions de base

Classes et Objets

Construction et destruction d’objets

Les fonctions amies

La surdéfinition d’opérateurs

Les patrons de fonctions et de classes

Les flots

La technique de l’héritage

Les espaces de nommage

Notions de Base

Christophe Collard

1. Les variables définies par l'utilisateur

Type de donnée Signification Taille (en octets) Plage de valeurs acceptée

char Caractère 1 -128 à 127

unsigned char Caractère non signé 1 0 à 255

short int Entier court 2 -32 768 à 32 767

unsigned short int Entier court non signé 2 0 à 65 535

int Entier

unsigned int Entier non signé

long int Entier long 4 -2 147 483 648 à 2 147 483 647

unsigned long int Entier long non signé 4 0 à 4 294 967 295

float Flottant (réel) 4 -3.4*10-38 à 3.4*1038

double Flottant double 8 -1.7*10-308 à 1.7*10308

long double Flottant double long 10 -3.4*10-4932 à 3.4*104932

bool Booléen

2 (sur processeur 16 bits) 4 (sur processeur 32 bits)

-32 768 à 32 767 -2 147 483 648 à 2 147 483 647

2 (sur processeur 16 bits) 4 (sur processeur 32 bits)

0 à 65 535 0 à 4 294 967 295

Même taille que le type int, parfois 1 sur quelques

compilateurs

Prend deux valeurs : 'true' et 'false' mais une conversion implicite (valant 0 ou 1) est faite par le compilateur lorsque l'on affecte un entier (en réalité toute autre valeur que 0 est considérée comme égale à True).

1 octet = 8 bits

1 bit = 0 ou 1

Christophe Collard

Déclaration et initialisation

int n;

n = 10;int n = 10;

Le qualificatif « const »

const int n = 10;

La valeur de « n » ne change pas.

Expression constante = valeur calculée lors de la compilation

variables locales vs variables globales

Ex : ici 2*n*5 est une constante

Remarque : chaque instruction se termine par un « ; »

Christophe Collard

2. Les fonctions

Fonctionint

doublefloat

INPUTS OUTPUT

But : accomplir une tâche

Attention : une fonction ne peut renvoyer qu’un seul type

Fonction standard : float fctname (int, double)

Fonction sans argument : float fctname ()

Fonction sans valeur de retour : void fctname (int, double)

Remarque : une fonction bien programmée peut être lue sur 1 seul écran

Christophe Collard

3. Les boucles

But : effectuer plusieurs fois le même type d’opérations

Ex: sommer les 10 premiers entiers

Attention : en C++ il faut initialiser les variables, sinon une valeur aléatoire est attribuée

for (int i=0; i<10; i++)

type du compteur

initialisation du compteurreste dans la boucle tant que cette condition est vérifiée

Incrémente le compteur de 1

Christophe Collard

Remarque:

Les variables i et j sont locales à la fonction.

Pour renvoyer la valeur j vers l’extérieur, il faut écrire :

Christophe Collard

Interprétation

cout désigne un « flot de sortie » prédéfini

<< est un opérateur dont l’opérande de gauche est un flot

et l’opérande de droite est une expression de type qcq

Ici le flot cout reçoit la valeur « bonjour »

4. Les entrées / sorties en C++

Ecriture sur la sortie standard

La bibliothèque iostream contient les déclarations nécessaires à l’utilisation

des entrées / sorties en c++

Christophe Collard

Autre exemple

Remarque

Les 2 dernières lignes peuvent s’écrire :

cout << ’’valeur de n = ‘’ << n << endl;

Interprétation

On transmet dans un premier temps une chaine de caractères au flot cout

Ensuite le flot est augmenté de la valeur de l’entier n

cout sait gérer des données de différents typesChristophe Collard

Rôle de l’opérateur différent dans ces deux cas

L’opérateur a procédé au formatage (implicite) de la valeur de n pour la

transformer en une chaine de caractères.

La possibilité d’attribuer plusieurs significations à un même opérateur :

SURDEFINITION D’OPERATEURS

Lecture sur l’entrée standard

cin >> n;

cin >> n >> p;

Christophe Collard

5. La notion de référence

Il existe 3 façons de transmettre des variables à une fonction :

- transmission par valeur

- transmission par adresse

- transmission par référence

Christophe Collard

Transmission par valeur

avant appel : 10 20

début échange : 10 20

fin échange : 20 10

après échange : 10 20

adresse

valeur

adresse

valeur

n a

les valeurs de n et p sont dupliquéeson change les valeurs des copies

Christophe Collard

Transmission par adresse

avant appel : 10 20

début échange : 10 20

fin échange : 20 10

après échange : 20 10

adresse

valeur

n a

les valeurs de n et p ne sont pas dupliquées

on change les valeurs des originauxChristophe Collard

Transmission par référence

avant appel : 10 20

début échange : 10 20

fin échange : 20 10

après échange : 20 10

adresse

valeur

n a

les valeurs de n et p ne sont pas dupliquées

on change les valeurs des originauxChristophe Collard

Remarques

la transmission par référence utilise

la simplicité de la notation de la transmission par valeur

le mécanisme de la transmission par adresse

L’utilisation de la transmission par référence s’écrit uniquement au

niveau de la fonction appelée :

void echange (int& a, int& b)

Attention aux effets de bord lors de l’appel de la fonction

echange (n, p)Appel de la fonction :

transmission par valeur ? transmission par référence ?

pas de modification des valeurs de n et p valeurs de n et p modifiéesChristophe Collard

6. Surdéfinition de fonctions

une fonction avec un même nom possède plusieurs significations

sosie numero 1 : a = 5

sosie numero 2 : a = 2.5

Que se passe t il si x est de type float,

long double, …?

conversion du type par le compilateurChristophe Collard

7. L’allocation dynamique de mémoire

l’opérateur NEW sert à allouer de la mémoire

l’opérateur DELETE sert à libérer de la mémoire

Exemple 1

Exemple 2

Pour allouer n éléments d’un « type » donné : new type [n]

new retourne un pointeur (type*) sur le 1er élément d’un tableau

adresse

valeur

p

p[0]

adresse

valeur

adresse

valeur

adresse

valeur

adresse

valeur

p[4]

L’opérateur NEW

Christophe Collard

L’opérateur DELETE

libère la mémoire allouée par l’opérateur NEW

on donne comme argument l’adresse du pointeur fournie par new

syntaxe pour les éléments de type C++ standard

int* p;

p = new int [5];

delete p;

syntaxe pour les tableaux d’objet

point* p;

p = new point [5];

delete [ ] p;

Attention le rôle de l’opérateur delete est très important.

Si on détruit un pointeur sans libérer correctement la mémoire,

celle-ci n’est plus accessible et ne peut être réallouée

Stack overflowChristophe Collard

Classes et Objets

Christophe Collard

1. Classes et encapsulation des données

généralisation de la notion de type

extension des types C++ standard à de nouveaux types définis pas l’utilisateur

regroupe des données et des méthodes

données membres fonctions membres

Classe

On a séparé les données et fonctions membres en 2 catégories

public private Christophe Collard

Encapsulation

private : données et méthodes non accessibles à l’extérieur de la classe

seules les fonctions membres y ont accès

protected : données et méthodes non accessibles à l’extérieur de la classe

accès possible par les classes dérivées (cf plus tard)

public : données et méthodes accessibles à l’extérieur de la classe

Remarques

pour modifier des données privées il faut passer via des méthodes publiques

En POO pure, les données sont encapsulées et leur accès ne peut se faire

que par le biais de méthodes

Christophe Collard

Définition des fonctions membres (méthodes)

x et y modifiablesinitialise méthode de point

le symbole :: est un opérateur de résolution de portée

l’identificateur initialise est celui défini dans la classe point

Christophe Collard

Utilisation de la classe

Remarques

point est un nouveau type défini par l’utilisateur

a et b sont des instances de la classe point

a et b sont encore appelés des objets de type point

si aucun des mots private ou public n’apparaît dans la classe, tout

est considéré comme étant private => rien n’est accessible

Christophe Collard

Affectation d’objets

Christophe Collard

Affectation d’objets

adresse

valeur

adresse

valeur

y y

adresse

valeur

x

adresse

valeur

x

b a

copie des membres

Christophe Collard

Remarques

seules les données membres sont copiée (pas les méthodes)

ceci n’est possible que pour des objets de même type

ce système de copie « partielle » ne fonctionne pas pour des

données dynamiques (il faudra surdéfinir un opérateur =)

Affectation d’objets

Christophe Collard

2. Constructeur et destructeur

création d’un nouvel objet

initialisation de ses données

allocation de mémoire

Processus automatisé

CONSTRUCTEUR

destruction d’un objet

libération de mémoire

Processus automatisé

DESTRUCTEUR

Fonctions membres appelées automatiquement

à chaque création / destruction d’objet

Christophe Collard

Exem

ple

Résulta

t: affic

he 1

0 v

ale

urs

alé

ato

ires

Christophe Collard

Remarques

le constructeur ne renvoie rien (même pas void)

le destructeur ne renvoie rien et ne prend aucun argument

a partir du moment où la classe possède un contructeur, il faut créer

un objet avec les arguments requis pas le constructeur

une classe peu contenir plusieurs constructeurs

le constructeur porte le même nom que la classe

le destructeur porte le nom de la classe précédé du symbole ~

hasard suite (); invalide ici

une classe ne peut contenir qu’un seul destructeur (car pas d’argument)

constructeur par défaut

constructeur d’initialisation des membres

constructeur par recopie

Christophe Collard

Attention :

le rôle du destructeur est très important.

Si on détruit un objet sans libérer correctement la mémoire, celle-

ci n’est plus accessible et ne peut être réallouée

Stack overflow

Christophe Collard

3. Les données membres statiques

Les différents objets issus d’une même classe possèdent chacun leurs

propres données membres

La déclaration suivantepoint a, b;

conduit à

adresse

valeur

adresse

valeur

y y

adresse

valeur

x

adresse

valeur

x

a b

Christophe Collard

Une façon de permettre à plusieurs objets de partager des données

consiste à les déclarer avec le qualificatif static

adresse

valeur

n

adresse

valeur

x

adresse

valeur

x

a b

Les membres statiques existent en 1 seul exemplaire, indépendamment

des objets de la classe correspondante (même si aucun objet existe)

Les membres statiques sont toujours initialisés à 0

static int ctr = 5; INTERDIT par le compilateurChristophe Collard

4. Exploitation d’une classe

Dissocier l’implémentation d’une classe de son utilisation

Mettre dans un fichier séparé la classe et son implémentation

Création de bibliothèques que l’on regroupe par thèmes

5. Propriétés des fonctions membres

Surdéfinition des fonctions membres

La surdéfinition de fonctions « ordinaires » en C++ s’applique

aux fonctions membre d’une classe, y compris au constructeur

Elle ne peut s’appliquer au destructeur qui ne reçoit aucun argumentChristophe Collard

Exem

ple

Christophe Collard

Résultat

position (0,0)

coordonnees du point

position (5,5)

Point

position (3,12)

Remarques

N’importe quelle méthode peut appeler une autre méthode de la

même classe (public, protected ou private).

N’importe quelle méthode peut s’appeler elle-même (récursivité),

mais il faut prévoir un moyen de finir le processus.

Pour accéder aux données/méthodes private ou protected, il faut

passer via un méthode publique de la classe.

On peut définir dans des fonctions des arguments par défaut afin de

limiter le nombre de fonctions surdéfinies Christophe Collard

Arguments par défaut

Dans la définition de la classe point, on peut remplacer

void affiche ();

void afficher (char*);

parvoid affiche (char* = ‘’’’);

void point::affiche (); est supprimée

void point::affiche (char* message=‘’’’);

Remarque

Ceci s’applique aussi aux constructeurs Christophe Collard

Les objets transmis en argument d’une fonction membre

définir une méthode « coincide » dans la classe point pour

comparer 2 objets de type point

Exemple

son appel s’effectue de la manière suivante

a.coincide (b)

ou par symétrie du problème

b.coincide (a)

Christophe Collard

Résultat

a et b 0 (false)

b et c 1 (true)Christophe Collard

Remarques

Appel du constructeur avec 1 seul argument

point b (1); point b (1,0);

Le second argument est initialisé avec la valeur par défaut

Ici, les objets sont transmis par copie à la fonction coincideChristophe Collard

Remarques

le principe d’encapsulation est-il violé ?

a.coincide(b)

l’objet « a » accède aux données privées de l’objet transmis « b »

En C++, l’unité de protection est la classe et non l’objet.

Si A et B sont 2 classes différentes, une fonction membre de A ne

peut accéder aux données privées de B (sauf à la déclarer comme

amie de la classe B – cf. plus tard) Christophe Collard

Transmission d’un objet par adresse

adresse

valeur

adresse

valeur

y

y

adresse

valeur

x

adresse

valeur

x

a

b

adpt

a.coincide (b)

Christophe Collard

Attention aux effets de bord

la transmission par adresse est efficace car les données ne sont

pas dupliquées (gain de mémoire, gain de temps)

les données de l’objet transmis ne sont pas protégées contre les

modifications

pour protéger les données de l’objet transmis de toute modification,

on utilise le qualificatif const :

dans la déclaration de la classe

dans l’implémentation de la fonction

les données de l’objet appelant sa fonction membre ne peuvent être

protégées

Christophe Collard

Transmission d’un objet par référence

Les remarques précédentes sur les effets de bord restent valable

Attention : la transmission par valeur (copie) d’objets contenant des

variables allouées dynamiquement pose problème ! Christophe Collard

Retour d’un objet par une fonction

par valeur

par adresse

par référence

la transmission d’objet par valeur ne fait qu’une copie partielle de l’objet

(attention aux objets contenant des pointeurs)

si une fonction retourne un objet par adresse ou par référence, il faut

éviter que l’objet retourné soit local (celui-ci étant détruit à la sortie de la

fonction !)

point& point::symetrique ();retour incorrect (res est détruit à la

sortie de la fonction duplique)Christophe Collard

Auto-référence : le mot clé this

On peut avoir besoin d’utiliser l’adresse d’un objet ayant appelé une fonction

A l’intérieur de la méthode affiche, on ne connaît pas le nom de l’objet ayant

appelé cette fonction.

Quand on en a besoin, on peut y accéder grâce au mot clé this.

Christophe Collard

Les fonctions membres constantes

Rappel

const int n = 20;

La variable n est constante et n’évolue pas (calculée à la compilation)

On peut définir des objets constants

Notion non triviale

Les opérations sur les objets sont réalisées par ses méthodes.

L’utilisateur peut préciser les fonctions membres

autorisées à travailler avec des objets constants

Christophe Collard

La méthode affiche est autorisée à travailler avec des objets constants.

Elle peut modifier les valeurs d’un objet de type point.

Il est possible de surdéfinir une fonction membre en se basant sur la

présence ou non du qualificatif const.

void affiche () const; // fonction 1

void affiche (); // fonction 2

a.affiche(); appelle la fonction 1

c.affiche(); appelle la fonction 2ExChristophe Collard

Construction, destruction et

initialisation d’objets

Christophe Collard

Les objets automatiques & statiques

Durée de vie

Les objets automatiques: créés par déclaration dans une fonction ou

un bloc et détruits à la sortie de cette fonction ou de ce bloc.

Les objets statiques: créés par déclaration en dehors de toute

fonction ou dans une fonction avec le qualificatif « static ». Ils existent

avant l’exécution de la fonction main et sont détruits a la fin de

l’exécution du programme

Les objets temporaires

Appel direct au constructeur d’une classe

objet temporaire

Christophe Collard

Exemple

point (1,2); appel direct au constructeur de la classe point

objet temporaire

a = point (1,2); copie l’objet temporaire dans a

La copie fonctionne car par d’allocation dynamique de mémoire dans ‘’point’’

L’objet temporaire est détruit quand il n’est plus utilisé (ici a la fin du main)Christophe Collard

Les objets dynamiques

Classes sans constructeur

déclaration d’un objet dynamique point* adr;

allocation dynamique de mémoire adr = new point;

réserve 2 emplacements mémoire pour stocker des données de type int

accès aux méthodes adr -> initialise (1,3);

adr -> affiche ();

(*adr).initialise (1,3);

(*adr).affiche ();

destruction (explicite) de l’objet delete adr;

Christophe Collard

Classes avec constructeur(s)

déclaration d’un objet dynamique point* adr;

allocation dynamique de mémoire adr = new point (1,2);

appel au constructeur point (int, int)

Christophe Collard

Lorsqu’il y a plusieurs constructeurs, l’opérateur new choisit le bon

constructeur grâce au nombre et/ou à la nature des arguments

Remarques

S’il n’existe pas de constructeur ou s’il existe un constructeur sans

argument, new point; ou new point (); sont acceptés

Si tous les constructeurs possèdent au moins un argument, new point;

et new point (); sont rejetés

Christophe Collard

Le constructeur par recopie

Mise en évidence du problème

Christophe Collard

schéma de l’opération effectuée lors de l’appel de la méthode add

transmission de b par valeur

size

p

b

tableau dynamique de double

Christophe Collard

schéma de l’opération effectuée lors de l’appel de la méthode add

transmission de b par valeur

size

p

b

tableau dynamique de double

size

p

v

copie des données de b dans v

• copie de size (int)

• copie p (pointeur)

b.p et v.p pointent

sur le même tableau

Christophe Collard

schéma de l’opération effectuée lors de la sortie de la fonction add

destruction de la copie v

size

p

b

tableau dynamique de double

size

p

v

appel au destructeur

• libère v.size

• libère le tableau situé en v.p

Christophe Collard

retour au main

b.p ne pointe plus sur rien

size

p

b

appel au destructeur

• libère b.size

• libère le tableau situé en b.p

fin du main ()

segmentation fault

Christophe Collard

Solution

size

p

b

size

p

v

dupliquer le tableau de valeurs

On définit un construteur par recopie (appelé automatiquement lors

de la copie d’un objet) de la forme :

vector (const vector&); vector (vector&);ou bien

En général, un constructeur par recopie n’a pas de raison de modifier l’objet

passé en argument. De plus, une fonction prévue pour un objet constant

peut toujours s’utiliser pour un objet non constant (réciproque fausse)

vector (const vector&); Christophe Collard

Application

etc …

Christophe Collard

Résumé

La transmission par valeur d’un argument ou d’une valeur de retour d’une

fonction met en œuvre une recopie. Elle est réalisée soit:

• par le constructeur de recopie par défaut (si aucun n’a été défini)

• par le constructeur de recopie surdéfini dans la classe

Lorsqu’un objet comporte des données dynamiques, il est

indispensable de définir un constructeur par recopie

On y indique comment dupliquer correctement les données de l’objet

Christophe Collard

Les tableaux d’objets

En C++ un tableau peut posséder des éléments de n’importe quels

types, y compris ceux définis par les utilisateurs via les classes

On peut déclarer un tableau « courbe » de points:

point courbe [20];

Chaque élément du tableau peut accéder aux méthodes de sa classe :

courbe[10].affiche();

Christophe Collard

Remarques

• Un tableau d’objets n’est pas un objet

• En POO pure, le concept de tableau d’objet n’existe pas

• Il est toujours possible de définir une classe dont un des membres

est un tableau d’objets

class courbe

{ point p [20];

…..

}

Un constructeur par défaut est appelé pour chaque élément du tableau

• soit la classe ne possède aucun constructeur

• soit elle doit posséder un constructeur par défaut

Christophe Collard

Exemple

point (7,0) point (3,0) point (11,0) point (0,0) point (0,0)

tableau de 5 objets de type point

Christophe Collard

Les tableaux dynamiques d’objets

création du tableau dynamique d’objets

• soit la classe ne possède aucun constructeur

• soit elle doit posséder un constructeur par défaut

destruction du tableau dynamique d’objets

delete [ ] adcourbe;

indique qu’il s’agit d’un tableau d’objets

Christophe Collard

Objets membre

Une classe peut posséder des données membre qui soient définis

par l’utilisateur via une classe :

Christophe Collard

Les fonctions amies

Christophe Collard

POO pure Encapsulation des données

données membres privées accessibles seulement

par les méthodes publiques de la classe

une méthode d’une autre classe doit passer via les

méthodes publiques de la classe pour accéder aux

données privées

problème dans certains cas

Exemple

On définit une classe vector et une classe matrix.

Produit matrice-vecteur nécessite l’accès aux données privées des 2 classes

Christophe Collard

Solutions

• déclarer les données dans la partie public

• utiliser des méthode publiques pour accéder aux données privées

• arrêter le C++ et se remettre au fortran

• utiliser des fonctions amies dans ses classes

Christophe Collard

Solutions

• déclarer les données dans la partie public

• utiliser des méthode publiques pour accéder aux données privées

• arrêter le C++ et se remettre au fortran

trop tard vu l’investissement déjà réalisé

• utiliser des fonctions amies dans ses classes

Christophe Collard

Solutions

• déclarer les données dans la partie public

perte du bénéfice de l’encapsulation (protection des données)

• utiliser des méthode publiques pour accéder aux données privées

• arrêter le C++ et se remettre au fortran

trop tard vu l’investissement déjà réalisé

• utiliser des fonctions amies dans ses classes

Christophe Collard

Solutions

• déclarer les données dans la partie public

perte du bénéfice de l’encapsulation (protection des données)

• utiliser des méthode publiques pour accéder aux données privées

oui, mais pas toujours optimal pour protéger les données d’un objet

• arrêter le C++ et se remettre au fortran

trop tard vu l’investissement déjà réalisé

• utiliser des fonctions amies dans ses classes

Christophe Collard

Il existe plusieurs situations d’amitié

• fonction indépendante amie d’une classe

• fonction membre d’une classe et amie d’une autre classe

• fonction amie de plusieurs classes

• toutes les fonctions membre d’une classe, amies d’une autre classe

Fonction indépendante amie d’une classe

Une fonction amie se déclare avec le mot clé friend

Exemple

Christophe Collard

Résultat a et b coincident

a et c ne coincident pas Christophe Collard

Remarques

l’emplacement de la déclaration d’amitié à l’intérieur de la classe

n’a pas d’importance

on ne peut pas utiliser d’argument implicite (this) dans une

fonction amie, car elle n’appartient pas à la classe

en général, une fonction amie possède 1 ou plusieurs arguments

et/ou une valeur de retour du type de la classe ( qui justifie la

déclaration d’amitié)

quand une fonction amie retourne un élément du type de la

classe, il est fréquent que ce soit un objet local à la fonction.

La transmission doit alors s’effectuer par valeur.

Christophe Collard

ici les arguments de coincide sont transmis par valeur

on pourrait les transmettre par référence

Fonction membre d’une classe et amie d’une autre

cas particulier de la situation précédente

indiquer dans la déclaration d’amitié à quelle classe elle appartient

utiliser l’opérateur de résolution de portée ::

la fonction f appartient à la classe B

la fonction f est amie de la classe A

la fonction f accède aux

données de A et B

Christophe Collard

Remarques

le compilateur a besoin de connaître les caractéristiques de B pour

compiler la classe A.

friend int B::f (char, A);

int f (char, A);

le compilateur a besoin se savoir que la classe A existe, mais sans

connaître ses caractéristiques.

Christophe Collard

Ecriture correcte du code

Christophe Collard

Fonction amie de plusieurs classes

une fonction, qu’elle soit indépendante ou bien membre d’une classe

peut faire l’objet de déclaration d’amitié dans plusieurs classes

f peut accéder aux données privées de A et de BChristophe Collard

Toutes les fonctions d’une classe sont amies d’une autre

C’est la généralisation de la notion de fonction amie

On pourrait déclarer toutes les fonctions d’une classe B comme

amies d’une classe A, mais il est plus simple de le faire de

manière globale dans la class A :

Christophe Collard

Une application de fonction amie indépendante

Christophe Collard

Une application de fonction amie membre d’une classe

Christophe Collard

La surdéfinition d’opérateurs

Christophe Collard

Christophe Collard

On considère une classe vector 2D :

class vector

{ int x,y;

};

On définit 2 objets de type vector a et b

a

b

Peut on écrire comme pour un type standard C++ la somme a + b ?

Christophe Collard

Il faut surdéfinir l’opérateur + pour la classe

définir une fonction operator + au sein de la classe

utiliser le mot clé operator suivi de l’opérateur à surdéfinir

la fonction operator + peut être :

• soit une fonction membre de la classe

• soit une fonction indépendante amie de la classe

• soit une fonction indépendante de la classe

Afin de protéger les données et d’accélérer le code, on choisit en général

de surdéfinir l’opérateur comme fonction indépendante amie de la classe.

Christophe Collard

Surdéfinition d’opérateur avec une fonction amie

Résultat

coordonnees (1,2)

coordonnees (2,5)

coordonnees (3,7)

coordonnees (6,14)

Christophe Collard

Surdéfinition d’opérateur avec une fonction membre

Résultat identique

Christophe Collard

Remarques

la fonction operator + est appelé de la manière suivante :

fontion indépendante : a + b operator + (a,b)

fontion membre : a + b a.operator + (b)

la fonction membre operator + fait apparaître une dissymétrie et

l’objet a ne peut pas être protégé

Opérateurs et transmission par référence

Dans les deux exemples précédents, on utilise la transmission par valeur

Pour des objets de grande taille, il vaut mieux utiliser la transmission

par référence. On peut alors protéger les objets transmis avec ‘’const’’

point operator + (const point& a, const point&b)

Le retour de l’objet point se fait obligatoirement par valeur

Christophe Collard

Les opérateurs ++ et --

Résultat

a1 (3,6)

b (2,5)

a2 (3,6)

b (3,6)

Christophe Collard

Surdéfinition de l’opérateur =

En l’absence de sudéfinition de l’opérateur =, il y a une simple recopie

du 2nd opérande dans le 1er

pose problème pour les objets contenant des pointeurs

size

p

a

tableau dynamique de double

size

p

b

vector a(5), b;

b = a;

cf. constructeur par recopie

Christophe Collard

Christophe Collard

Surdéfinition de l’opérateur [ ]

exemple de la classe vector

l’opérateur [ ] permet d’accéder au ième élément du vecteur

En informatique on commence à compter à partir de 0

En mathématiques on commence à compter à partir de 1

C’est l’opérateur [ ] qui fera la conversion

C++ impose de définir l’opérateur [ ] comme fonction membre

int& operator [ ] (int);

retour par référence obligatoire afin d’utiliser l’opérateur pour affecter

des valeurs

Christophe Collard

Résultat 3 6 9

Christophe Collard

Remarque

L’opérateur [ ] ne peut pas être appliqué à un objet constant.

Il aurait fallut le définir de la façon suivante

int& operator [ ] (int) const;

Christophe Collard

Surdéfinition des opérateurs new et delete

La surdéfinition se fait obligatoirement par une fonction membre

La fonction NEW reçoit un argument de type size_t (bibliothèque stddef)

taille en octets de l’objet à allouer

La fonction NEW renvoit un void* (adresse où est stocké l’objet)

La fonction DELETE reçoit un pointeur en argument (adresse objet)

La fonction ne renvoit rien (void)

Remarques

La surdéfinition de l’opérateur new implique la prise en charge de la

gestion de la mémoire

NEW et DELETE ne reçoivent pas d’argument implicite (this)

Christophe Collard

Christophe Collard

Résultat

++ nombre total de points = 1

++ nombre total de points dynamiques = 1

++ nombre total de points = 2

++ nombre total de points = 3

++ nombre total de points dynamiques = 2

++ nombre total de points = 4

-- nombre total de points = 3

-- nombre total de points dynamiques = 1

-- nombre total de points = 2

-- nombre total de points dynamiques = 0

-- nombre total de points = 1

-- nombre total de points = 0

point a(3,5);

new point (1,3);

appel implicite par new

point b;

new point (2,0);

appel implicite au constructeur

appel implicite par delete ad1

delete ad1;

appel implicite par delete ad2

delete ad2

fin prog. destruction de a

fin prog. destruction de b

Action Affichage

Christophe Collard

Remarques

La surdéfinition des opérateurs NEW et DELETE n’a d’incidence que

sur les objets dynamiques

Que NEW soit surdéfini ou non, son appel est toujours implicitement

suivi de celui d’un constructeur

De même, DELETE fait appel implicitement à un destructeur

Il est toujours possible de définir les opérateurs NEW et DELETE de

manière globale

déclarer NEW et DELETE comme fonctions indépendantes

appel à cet opérateur par tous les types (y compris

ceux de base du C++)

plus de possibilité d’appeler l’opérateur new prédéfini

ex int* adi = new int; y fait appel

Christophe Collard

Les patrons de fonctions

Les patrons de classes

Christophe Collard

La surdéfinition de fonctions permet de donner un nom unique à plusieurs

fonctions réalisant un travail différent

La notion de patron est plus puissante et plus restrictive

Plus puissante

on écrit une seule fois la définition d’une fonction pour que le compilateur

puisse l’adapter automatiquement à n’importe quel type

Plus restrictive

toutes les fonctions ainsi fabriquées ont la même définition et le même

algorithme

But

écrire une fonction qui soit valable quel que soit le type des arguments

utilisés

Christophe Collard

Exemple

int min (int a, int b)

{ return (a < b) ? a : b;

}

float min (float a, float b)

{ return (a < b) ? a : b;

}

double min (double a, double b)

{ return (a < b) ? a : b;

}

long int min (long int a, long int b)

{ return (a < b) ? a : b;

}

etc …

On écrit la même fonction pour tous les types existant en C++

c’est long, très long, très très long

et en plus il faut le faire pour toutes les fonctions

ça multiplie les lignes de code et rend le code illisible

il faut compléter le code quand on définit ses propres classes

Christophe Collard

On résout ce problème en utilisant les patrons de fonctions

cette méthode est très puissante

Elle permet de définir des méthodes pour des types qui n’existent pas encore

patron type

fonction

Résultat min (n,p) = 4

min (x,y) = 2.5

Christophe Collard

Application à un type classe

Remarque il suffit de donner un sens à l’opérateur < pour des objet de

type point pour pouvoir utiliser min (sans rien ajouter !)

Christophe Collard

Généralisation et conversion

Quel type retourne fct ?

Christophe Collard

Généralisation et conversion

fct (n, x, p) int (conversion de float vers int pour x)

fct (x, n, y) float (conversion de int vers float pour n)

fct (n, p, q) int

fct (n, p, x) erreur (ne pas laisser choisir le compilateur à votre place !)

Christophe Collard

Généralisation et conversion

fct (n, x, p) int (conversion de float vers int pour x)

fct (x, n, y) float (conversion de int vers float pour n)

fct (n, p, q) int

fct (n, p, x) erreur (ne pas laisser choisir le compilateur à votre place !)

Remarque dans fct, on peut initialiser des variables de type T ou U

Christophe Collard

exemple

Christophe Collard

Surdéfinition des patrons

Remarque

on peut transmettre des éléments de n’importe quel type aux fonctions

grâce aux patrons

les fonctions surdéfinies doivent avoir un nombre d’arguments différent

afin d’éviter les ambigüités

Christophe Collard

Les patrons de classes

Mise en évidence du problème

Comment stocker des points avec des coordonnées int, float, double, … ?

Utiliser des patrons de classe

Christophe Collard

La définition inline :

La définition à l’extérieur de la classe :

nom de la classe

nom du patronnom de la fonciton

Christophe Collard

Réécriture du code

Christophe Collard

Les flots

Christophe Collard

les opérateurs << et >> assurent le transfert de l’information

le formatage de l’information

Le flot cout est connecté à la sortie standard

Le flot cin est connecté à l’entrée standard

Un flot est un objet d’une classe prédéfinie :

ostream pour le flot de sortie

istream pour le flot d’entrée

Chacune de ces 2 classes surdéfinit les opérateurs << et >> pour les

différents types de base du C++ (fichier iostream)

Christophe Collard

Surdéfinition des opérateurs << et >>

Christophe Collard

La technique de l’héritage

Christophe Collard

Le concept de l’héritage (ou de classes dérivées) constitue l’un des

fondements de la POO

Intérêt

classe de base

classe dérivée

propriétés de la classe

propriétés classe de base + nouvelles propriétés

Classe dérivée :

• nouvelle classe

• définie à partir de la classe de base

• hérite des propriétés de la classe de base

• ajoute de nouvelles propriétés à la classe de base

• ne modifie pas la classe de base

permet de développer de nouveaux outils en se basant sur les acquis de

la classe de base

Christophe Collard

Remarque

L’héritage n’est pas limité à un seul niveau

• une classe dérivée peut devenir classe de base pour une autre classe

• plusieurs classes peuvent être dérivées d’une même classe

Christophe Collard

Mise en œuvre de l’héritage

Classe de base

Christophe Collard

Classe dérivée

On ajoute une information à cette classe : la couleur du point

Programme principal

Christophe Collard

Utilisation des membres d’une classe de base dans une

classe dérivée

Quand on appelle p.affiche() pour un objet de type pointcol, cette fonction

n’est pas définie dans la classe enfant (pointcol)

C’est la fonction affiche de la classe parent (point) qui est appelée

C’est la fonction affiche de la classe parent (point) qui est appelée

Christophe Collard

Utilisation des membres d’une classe de base dans une

classe dérivée

Quand on appelle p.affiche() pour un objet de type pointcol, cette fonction

n’est pas définie dans la classe enfant (pointcol)

C’est la fonction affiche de la classe parent (point) qui est appelée

C’est la fonction affiche de la classe parent (point) qui est appelée

Définir une méthode affichec () dans pointcol du type :

Christophe Collard

Problème :

pointcol n’a pas accès aux données privées de point (x et y)

soit mettre les données de point dans la partie protected

soit utiliser une méthode publique de point

Surdéfinition des fonctions membre

les fonctions affiche () et afficec () effectuent les même tâches

leur donner le même nom (surdéfinition)

Christophe Collard

Christophe Collard

Appel des constructeurs et destructeurs

Christophe Collard

Le constructeur par recopie

Christophe Collard

Le contrôle des accès

But : protection des données de la classe de base

les données et méthodes privées sont inaccessibles en dehors leur classe

les données et méthodes publiques sont accessibles partout

comment protéger les données de la classe de base et les rendre

accessibles par la classe dérivée ?

Christophe Collard

Le contrôle des accès

But : protection des données de la classe de base

les données et méthodes privées sont inaccessibles en dehors leur classe

les données et méthodes publiques sont accessibles partout

comment protéger les données de la classe de base et les rendre

accessibles par la classe dérivée ?

définir les données et méthodes protégées

Christophe Collard

Remarques

les fonctions amies d’une classe dérivée possèdent les même droits

que les fonctions membre

la déclaration d’amitié ne s’hérite pas

f : fonction amie de la classe A

B : classe dérivant de la classe Af n’est pas amie de B

il est possible d’effectuer des dérivations différentes de public

class B : public class A

statut initial accès aux FMA accès externe nouveau statut accès externe nouveau statut accès externe nouveau statut accès externe

public public protected private

protected protected protected private

private private private private

classe de base dérivée public dérivée protected dérivée private

Christophe Collard

Utilisation

classe de base

dérivée 3dérivée 2dérivée 1 dérivée 4

partie commune d’un problème

solution 1 solution 2 solution 3 solution 4

gain de temps en programmation

par de pénalité de temps pour les fonctions non utilisées dans la

classe dérivée, car ne sont pas inclues lors de l’édition de lien

perte de temps lors d’appel de fonctions imbriquées

Christophe Collard

L’héritage multiple

Christophe Collard

Les espaces de nommage

Christophe Collard

zones de déclaration permettant de délimiter la recherche des noms

des identificateurs par le compilateur

Mot clé : namespace

But

regrouper les identificateurs logiquement pour éviter les conflits de

nom entre plusieurs parties d’un même projet

Remarque

par défaut, C++ utilise un espace de nommage (namespace std) de

portée globale dans lequel il doit y avoir aucun conflit de nom

Définition d’un espace de nommage

Christophe Collard

Remarque

un namespace peut être découpé en plusieurs morceaux

les identificateurs définis à l’intérieur d’un même namespace

ne doivent pas entrer en conflit

Christophe Collard

Accès aux membres d’un namespace

Il se fait grâce à l’opérateur de résolution de portée

Définition de fonctions d’un namespace

La fonction peut aussi être implantée à l’extérieur du namespace

en utilisant l’opérateur de résolution de portée

Christophe Collard

On peut de même définir des classes dans un namespace

Définition d’un namespace dans un namespace

Alias de namespace

Lorsqu’un namespace porte un nom compliqué, il peut-être

avantageux de définir un alias

namespace nom_alias=nom;

Christophe Collard

La directive using

elle permet d’utiliser tous les identificateurs d’un namespace sans

spécifier cet espace devant chaque fonction ou variable