• Aucun résultat trouvé

Les types de donnée abstraits

Dans le document Programmation orientée objet avec C++ (Page 23-40)

COMPLEXE z1, z2, z3;

complexe_initialiser(&z1);

complexe_initialiser(&z2);

complexe_ecrire_cartesien(&z1, 3, 0);

complexe_ecrire_cartesien(&z2, 0, 2);

z3 = complexe_somme(z2, z1);

printf("z3 = %lf + i . %lf\n", complexe_lire_reelle(z3), complexe_lire_imaginaire(z3));

system("PAUSE");

return 0;

}

Attention. Mauvaise utilisation, car ne respecte pas l’abstraction du type.

Les types de donnée abstraits

Exemple d’utilisation incorrecte

#include "complexes.h"

int main() {

COMPLEXE z1 = {3.0, 0.0}, z2, z3;

z2.reel = 0.0;

z2.imaginaire = 2.0;

z3 = complexe_somme(z2, z1);

printf("z3 = %lf + i . %lf\n", complexe_lire_reelle(z3), complexe_lire_imaginaire(z3));

system("PAUSE");

return 0;

}

Introduction à la programmation orientée objet avec C++ 46

Introduction : Rappel – le TDA Nombre complexe en C - Analyse

void complexe_initialiser(COMPLEXE* z);

void complexe_ecrire_cartesien(COMPLEXE* z, double re, double im);

void complexe_ecrire_polaire(COMPLEXE* z, double module, double argument);

• Syntaxe fastidieuse

– Noms de méthodes préfixés par « complexe »

• pour rappeler le TDA d’appartenance

– Il faut toujours passer la structure en paramètre par adresse

• C++ : nouvelle syntaxe facilitant la programmation des TDA

– Des fonctions peuvent être déclarées dans un struct.

– On les appelle alors des « méthodes ».

– Ces méthodes ont accès directement aux variables de la struct.

Programmation orientée objet en C++

Les méthodes : des fonctions associées à la structure - déclaration struct Complexe

{

double reelle, imaginaire;

void DefinirCartesien(double re, double im);

void DefinirPolaire(double module, double argument);

double LireReelle();

double LireImaginaire();

double LireModule();

double LireArgument();

Complexe Oppose();

Complexe Conjugue();

};

Introduction à la programmation orientée objet avec C++ 48

Les méthodes : des fonctions associées à la structure - implémentation

void Complexe::DefinirCartesien(double re, double im) {

return sqrt(reelle * reelle + imaginaire * imaginaire);

}

Complexe Complexe::Conjugue() {

Complexe resultat;

resultat.DefinirCartesien(reelle, -imaginaire);

return resultat;

}

Dans l’implémentation, les méthodes sont préfixées par le nom du type.

Tous les champs de la structure sont accessibles directement depuis les méthodes.

Programmation orientée objet en C++

Les méthodes : des fonctions associées à la structure - utilisation

#include <iostream>

#include "complexe.h"

using namespace std;

int main() {

Complexe z1, z2;

z1.DefinirCartesien(1.5, 2.0);

z2 = z1.Conjugue();

On utilise le point pour accéder aux méthodes (comme pour les champs)

Syntaxe allégée. Le mot struct n’a pas besoin d’être répété.

Introduction à la programmation orientée objet avec C++ 50

Les méthodes : accès aux membres – comparaison C / C++

• En langage C

void complexe_definir_cartesien(COMPLEXE* z, double re, double im) {

z->reel = re;

z->imaginaire = im;

}

• En langage C++

void Complexe::DefinirCartesien(double re, double im) {

reelle = re;

imaginaire = im;

}

L’adresse de la structure est évidemment requise pour accéder aux champs.

L’adresse de la structure n’est pas passée, et pourtant ça fonctionne !?

Programmation orientée objet en C++

Les méthodes : accès aux membres

• Le pointeur « this »

– En C++, les méthodes reçoivent un paramètre invisible.

– Il s’appelle « this ».

– C’est un pointeur sur la structure sur laquelle la méthode est appelée.

• Code écrit :

void Complexe::DefinirCartesien(double re, double im) {

reelle = re;

imaginaire = im;

}

• De façon interne et silencieuse, le code vraiment compilé est :

void Complexe::DefinirCartesien (Complexe * this, double re, double im)

{

this->reelle = re;

this->imaginaire = im;

}

Introduction à la programmation orientée objet avec C++ 52

Gérer la visibilité : public et private

• Rappel –TDA

– TDA : Type de Données Abstrait.

– On ne devrait jamais accéder directement aux champs de la structure.

– Mais rien ne nous empêche de le faire !

• Mauvais exemple d’utilisation du TDA:

int main()

Accès direct aux champs.

Rompt l’abstraction.

Programmation orientée objet en C++

Gérer la visibilité : public et private

• C++ apporte des améliorations pour les TDA

– Possibilité d’interdire l’accès aux membres par les utilisateurs d’un type.

– Syntaxe : modificateurs public et private

• Exemple :

void DefinirCartesien(double re, double im);

void DefinirPolaire(double module, double argument);

double LireReelle();

double LireImaginaire();

. . . };

L’accès direct à ces champs hors des méthodes du type Complexe sera interdit par le compilateur.

Le type complexe peut seulement être utilisé avec les méthodes publiques prévues.

Garantit le respect de l’abstraction

Introduction à la programmation orientée objet avec C++ 54

Notion de classe

• La programmation orientée objet

– Elle est basée sur la notion de classe. (explicitée plus loin)

• Comment déclarer une classe en C++ ?

– Il suffit d’utiliser le mot class à la place du mot struct.

class Complexe {

private:

double reelle, imaginaire;

public:

void DefinirCartesien(double re, double im);

void DefinirPolaire(double module, double argument);

double LireReelle();

double LireImaginaire();

. . . . };

Programmation orientée objet en C++

Différence entre class et struct

• Points communs

– class et struct permettent tous deux de déclarer des classes.

– Le code généré est 100 % identique.

• Différences

– Avec la déclaration struct

• Par défaut, tous les membres sont publics.

– Avec la déclaration class

• Par défaut, tous les membres sont privés.

• Lequel préférer ?

– En programmation orientée objet, on utilise habituellement class.

– Par défaut, tout ce qui n’est pas explicitement rendu public par le programmeur est ainsi privé.

Introduction à la programmation orientée objet avec C++ 56

Notion d’objet

• Définition

– Un objet est une instance d’une classe.

– C’est-à-dire une variable de ce type.

• Exemples

Complexe z1, z2;

Complexe * z3;

z3 = new Complexe;

– z1 et z2 sont des objets.

– z3 est un pointeur sur un objet (son adresse).

Programmation orientée objet en C++

C++ et compilation séparée

• Le fichier .h

– Contient habituellement les déclarations de classes, méthodes, …

• Le fichier .cpp

– Contient l’implémentation des méthodes.

Introduction à la programmation orientée objet avec C++ 58

Surcharge des opérateurs

• Surcharge des opérateurs

– Permet de donner un sens nouveau aux opérateurs.

– Seulement pour les types définis par le programmeur.

• Exemple :

surcharge de << pour le type « Complexe » – Opérateur déclaré EN DEHORS de la classe.

ostream & operator<<(ostream & stream, const Complexe & z) {

stream << z.LireReelle();

if (z.LireImaginaire() < 0.0)

stream << " - " << - z.LireImaginaire() << " . i";

else if (z.LireImaginaire() > 0.0)

stream << " + " << z.LireImaginaire() << " . i";

return stream;

}

Programmation orientée objet en C++

Méthodes const

• Problème

– « z » est un paramètre const.

– A-t-on le droit d’appeler une méthode sur un const ? – Et si la méthode modifiait la constante ?

– Compilateur: refus des appels de méthodes normales sur des objets const

• Solution : déclarer les méthodes const

class Complexe {

. . . .

double LireReelle() const;

double LireImaginaire() const;

double LireModule() const;

double LireArgument() const;

. . . . };

Introduction à la programmation orientée objet avec C++ 60

Surcharge des opérateurs - utilisation

#include <iostream>

#include "complexe.h"

using namespace std;

int main() {

Complexe z1, z2;

z1.DefinirCartesien(1.5, 2.0);

z2 = z1.Conjugue();

Utilisation du nouvel opérateur

<<

Programmation orientée objet en C++

Surcharge des opérateurs – l’addition de complexes

• Déclaration d’un opérateur dans la classe

class Complexe {

public:

. . . .

Complexe operator+(const Complexe & operande);

. . . . };

• Implémentation

Complexe Complexe::operator+(const Complexe & operande) {

Complexe resultat;

resultat.reelle = reelle + operande.reelle;

resultat.imaginaire = imaginaire +

operande.imaginaire;

return resultat;

}

Introduction à la programmation orientée objet avec C++ 62

Surcharge des opérateurs – l’addition de complexes - utilisation

#include <iostream>

#include "complexe.h"

using namespace std;

int main() {

Complexe z1, z2;

z1.DefinirCartesien(1.5, 2.0);

z2.DefinirCartesien(3.0, 4.0);

cout << "z1 : ";

cout << z1 << endl;

cout << "z2 : ";

cout << z2 << endl;

cout << "z1 + z2 : " << z1 + z2 << endl;

}

Style de programmation naturel grâce aux opérateurs définis.

Programmation orientée objet en C++

Usages pour les noms des accesseurs

• Usage général

– Le code source est écrit en langue anglaise

• Méthodes d’accès en lecture

– On utilise le terme « get » : obtenir double GetReal() const();

double GetImaginary() const;

• Méthodes d’accès en écriture

– On utilise le terme « set » : définir void SetReal(double value);

• Terminologie

– On parle de « getter » et de « setter »

Introduction à la programmation orientée objet avec C++ 64

Initialisation et finalisation d’un TDA

• Principes d’utilisation des TDA

– Initialisation : préparer les variables internes avant l’utilisation.

– Utilisation normale.

– Finalisation : libérer les ressources allouées

• Exemple : libérer la mémoire allouée dynamiquement avec malloc.

– En C: initialisation et finalisation à appeler explicitement.

• Apport du C++

– Notion de constructeur

• Méthode d’initialisation d’un objet.

• Appelée automatiquement à la création de l’objet.

– Notion de destructeur

• Méthode de finalisation d’un objet.

• Appelée automatiquement à la destruction de l’objet.

Programmation orientée objet en C++

Constructeur - Introduction

• Exemple – objet non initialisé

int main()

{

Complexe z1;

cout << "z1 : ";

cout << z1 << endl; // non initialisé ! }

Introduction à la programmation orientée objet avec C++ 66

Constructeur – déclaration et définition

• Déclaration

class Complexe {

private:

double reelle, imaginaire;

public:

Complexe();

. . . };

• Définition

Complexe::Complexe() {

reelle = 0.0;

imaginaire = 0.0;

}

Méthode déclarée:

- Avec le nom de la classe.

- Sans aucun type de résultat.

Programmation orientée objet en C++

Constructeur

• Exemple – objet initialisé automatiquement

int main() {

Complexe z1; // Initialisé par le constructeur !

cout << "z1 : ";

cout << z1 << endl;

}

Introduction à la programmation orientée objet avec C++ 68

Constructeur paramétré

• Déclaration

class Complexe {

public:

Complexe();

Complexe(double re, double im);

. . . };

• Définition

Complexe::Complexe(double re, double im) {

DefinirCartesien(re, im);

}

Programmation orientée objet en C++

Constructeur

• Exemple – objet initialisé avec des paramètres

int main() {

Complexe z1(1.0, 2.5);

cout << "z1 : ";

cout << z1 << endl;

}

Introduction à la programmation orientée objet avec C++ 70

Objets membres et constructeur

• On construit une classe « SimulationImpedance »

• En utilisant un objet « Complexe » pour l’impédance

class SimulationImpedance {

private:

Complexe impedance;

double frequence;

public:

void DefinirFrequence(double f);

void DefinirImpedance(const Complexe & z);

};

Programmation orientée objet en C++

Objets membres et constructeur

• Utilisation

int main() {

SimulationImpedance s1, s2;

}

• Que se passe-t-il à la construction de s1, s2 ?

– Construction des objets interne.

– Appel automatique du constructeur de « Complexe ».

Introduction à la programmation orientée objet avec C++ 72

Une liste tableau simple en C++

• Exemple : liste de double

#define CAPACITE 100 class ListeDouble {

private:

double * tableau;

int nombre_elements;

public:

ListeDouble();

~ListeDouble();

ListeDouble(const ListeDouble & liste);

ListeDouble & operator=(const ListeDouble & valeur);

int Ajouter(double x);

int LireNombreElement() const;

double LireElement(int indice) const;

double operator[](int indice) const;

};

Programmation orientée objet en C++

Une liste tableau simple en C++

• Constructeur par défaut

ListeDouble::ListeDouble() {

nombre_elements = 0;

tableau = new double[CAPACITE];

}

• Libération de la mémoire

– La mémoire allouée dynamiquement doit être libérée.

– Solution en C++ : le destructeur

• Méthode appelée automatiquement lorsque l’objet disparait.

Introduction à la programmation orientée objet avec C++ 74

Destructeur

• Déclaration

class ListeDouble {

public:

ListeDouble();

~ListeDouble();

. . . };

• Définition

ListeDouble::~ListeDouble() {

delete []tableau;

}

Destructeur:

- Nom de la classe, précédé de ~ - Sans aucun type de résultat.

Programmation orientée objet en C++

Constructeur et destructeur – illustration int main()

{

ListeDouble liste1; // construction de liste1 ListeDouble liste2; // construction de liste2

// liste1 et liste2 sont utilisables liste1.Ajouter(2);

liste1.Ajouter(7);

liste1.Ajouter(4);

liste2 = liste1;

// A la sortie du bloc ou de la fonction // destruction automatique de liste2 // destruction automatique de liste1 }

Introduction à la programmation orientée objet avec C++ 76

Une liste tableau simple en C++

• Utilisation

int main() {

ListeDouble liste1, liste2;

liste1.Ajouter(3.0);

liste2 = liste1;

}

• Constat

– Objets très facile à utiliser.

– Construits et détruits automatiquement.

• Problème

// Que fait cette instruction ? liste2 = liste1;

– Exception à la fin du programme !

Programmation orientée objet en C++

Méthodes par défaut

• En C++, toute classe a au minimum

– 1 Constructeur par défaut.

– 1 Constructeur copie.

• Appelé lors de l’initialisation d’un objet.

• Copie chaque champ.

– 1 Opérateur d’affectation.

• Appelé lors de l’affectation d’un objet.

• Copie chaque champ.

• Par défaut, ces méthodes sont générées automatiquement.

Introduction à la programmation orientée objet avec C++ 78

Une liste tableau simple en C++ - initialisation incorrecte de l’objet

liste1 tableau nombre_elements

3 5 4 1 0 9 2 8 7 2 4 7

liste2 tableau nombre_elements

Dans le document Programmation orientée objet avec C++ (Page 23-40)

Documents relatifs