2ième classe (mercredi, 13 octobre) c++ intro csi2572

36
2ième Classe (Mercredi, 13 Octobre) 2ième Classe (Mercredi, 13 Octobre) C++ Intro C++ Intro CSI2572 CSI2572

Upload: urbain-gentil

Post on 03-Apr-2015

105 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

2ième Classe (Mercredi, 13 Octobre)2ième Classe (Mercredi, 13 Octobre)C++ IntroC++ IntroCSI2572CSI2572

Page 2: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

2 C A C++

Les commentaires

Il y a deux types de commentaires en C++ : les commentaires mono ligne et les blocs de commentaire.

Les commentaires mono ligne commencent par les symboles // et permettent de placer en commentaire la fin d'une ligne comme le montre le fragment de code suivant :

int i; // fin de la ligne en commentaire

Page 3: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

2 C A C++ II

Les types références

En C, il n`y avait qu'un seul mode de passage des paramètres : le passage par valeur (même le passage par adresse correspond à passer une adresse par valeur ). Supposons qu'une fonction ait besoin de modifier la valeur de l'un de ses paramètres. Comme seul le passage par valeur est supporté, il ne reste plus qu'à passer un pointeur sur l'objet à modifier.

En C++, on peut aussi passer par référence.

Problèmes:

Et si on passe un argument par valeur qui occupe beaucoup d’espace?La copie doit être mise sur le stack… Ce qui est inutile si on ne désire pas la modifier.

Page 4: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Les types références (syntaxe)

Une référence à un paramètre de fonction en C++ est un alias pour son argument correspondant. Pour indiquer qu’un paramètre de fonction doit être passé par réference, il suffit de faire suivre le type du paramètre de la fonction par le symbole &:

char* foo(int &a, char b);

C’est la même chose pour la déclaration d’un alias à une variable (une variable de type référence):

int a;int & ar = a;

Les variables de type référence doivent être initialisées lors de leur déclarations.

Attention: La syntaxe est néanmoins trompeuse car le signe de référence "&" est le même que celui de la prise d'adresse.

Page 5: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

/* En C d'abord */ void swapEntiers(int *a, int *b) {

int c = *a; *a = *b; *b = c;

}

int main(int argc, char *argv[]) { int i=5; int j=6; swapEntiers(&i, &j); return 0;

}

// Et maintenant en C++ void swapEntiers(int &a, int &b) {

int c=a; a = b; b = c;

}

int main(int, char **) { int i=5; int j=6; swapEntiers(i,j); return 0;

}

Page 6: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

ATTENTION:

#include <iostream>

int main(int, char **) { int i=5; int j=10; int &r=i;

cout << i << endl; // Affiche 5 cout << r << endl; // Affiche 5

r++; cout << r << endl; // Affiche 6 cout << i << endl; // Affiche 6

r=j; r++; cout << r << endl; // Affiche 11 cout << j << endl; // Affiche 10 cout << i << endl; // Affiche 11 !

return 0; }

ATTENTION:Les références qui ont été crées en variables ne peuvent plus être réassignées.

Page 7: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Surcharge des fonctions

La surcharge est un mécanisme qui permet de donnerdifférentes signatures d'arguments à une même fonction.

Vous pouvez nommer de la même façon des fonctions deprototypes différents.

L'intérêt est de pouvoir nommer de la même manière desfonctions réalisant la même opération à partir de paramètresdifférents.

2 C A C++ III

Page 8: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Exemple:

Vous travailliez sur un système de gestion d'interface utilisateur àbase de fenêtres. Chaque fenêtre est peut être identifiée de 2manières différentes:

1. Un identificateur numérique 2. le nom : une chaîne de caractères

Vous voulez écrire 2 fonctions qui permettent derécupérer un pointeur sur une fenêtre en utilisant soitl'identificateur numérique, soit le nom. Avec un système sanssurcharge, il vous faudrait utiliser 2 noms de fonctionsdifférents, par exemple :

Window *GetWindowIdent(unsigned long identificateurNumerique); Window *GetWindowName(const char *nom);

Page 9: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Surcharger vous permet d'utilisez le même nom :

Window *GetWindow(unsigned long identificateurNumerique);Window *GetWindow(const char *nom);

Page 10: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Le compilateur s'y retrouve parce que le nom « interne » de la fonction contient la liste des paramètres.

À la compilation, en consultant la liste des paramètres effectifs, le compilateur établit quelle est la forme de la fonction à appeler.

Il est impossible d'avoir des fonctions qui ne diffèrent que par leur type de retour. En effet, le compilateur ne peut pas les distinguer si on omet de récupérer la valeur retournée.

Page 11: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

2 C A C++ IVLes paramètres avec valeurs par défaut

C++ vous permet de spécifier une valeur par défaut au arguments de vos fonctions. De 7 manière, quand vous utilisez la fonction, vous n'avez à spécifier ces arguments que lorsque leur valeur diffère du défaut.

Les valeurs par défaut ne peuvent être spécifiés que lors de la déclaration de la fonction et ne doivent pas être rappelés lors de définition de la fonction.

Exemple:int Show (Window *p, unsigned int modeOuverture = 1);

Page 12: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Le nombre des paramètres avec des valeurs par défaut n'est pas limité. En fait, tous les paramètres peuvent prendre une valeur par défaut. Toutefois, seuls les derniers paramètres de la fonction peuvent avoir une valeur par défaut. Par exemple, le code suivant est illégal :

void f1(int i, double angle=0.0, double longueur);

De même, avec :

void f2(double angle=0.0, double longueur=50.0);

L'appel suivant est illégal :

f2(,35.0);

Vous ne pouvez omettre que les valeurs des derniers paramètres.

Page 13: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

2 C A C++ V

Les nouvelles primitives d'entrées / sorties

Les fonctionnalités d'entrées / sorties en C++ sont orientées objet. Elles reposent sur la notion de flux (en anglais: streams).

Leur utilisation se fait principalement au travers des opérateurs de redirection en sortie "<<" et en entrée ">>". Ainsi, l'écriture à l'écran d'une expression se traduit par le code suivant :

cout << expression;

Cela sous entend la surcharge de l'opérateur << pour le type de donnée correspondant à expression.

Ce travail a été réalisé pour la plupart des types atomiques du C++. Il vous appartiendra de le faire pour vos propres classes.

Page 14: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Objet Flux Périphérique "C" Description

cout stdout Flux associé à la sortie standard (écran)

cin stdin Flux associé à l'entrée standard (clavier)

cerr stderr Flux associé à la sortie des erreurs (écran)

Les flux standards Il y a 3 objets de type flux:

Page 15: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Les opérateurs << sont prévus pour être chaînés. Vous pouvez donc les cumuler sur la même ligne de code, par exemple:

int i; int j; cout << i << " " << j << endl;

La constante symbolique endl vous permet de changer de lignes indépendamment de l'architecture dans laquelle le programe évolue.

Page 16: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Comme avec les printf, Il est possible de spécifier des formats d'affichage à la manière des fameux "%6.2f".

Pour cela, il faut utiliser des manipulateurs de flux. L'exemple suivant créé l'équivalent d'un printf("6.2f",r);

#include <iostream> #include <iomanip> using namespace std;

int main(int, char **) { double r=36.145278; int i=5; cout << setw(6) << setprecision(2) << r

<< endl; cout << i << " " << i++ << endl; cout << i << endl; return 0;

}

36.14

6 5

6

Les appels sont réalisés de la droite vers la gauche.

Les expressions que vous affichez sont présentées dans l'ordre que vous avez demandé mais elles ont été évaluées dans l'ordre inverse.

Page 17: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

En plus des "anciens" malloc et free du C, C++ possède un nouveau jeu d'opérateurs d'allocation/désallocation de mémoire : new et delete.

Ils ont été créés principalement pour la gestion dynamique des objets, mais on peut les utiliser également pour des variables simples.

int * p = (int*)malloc(sizeof(int)); free(p); p = 0;

int * p = (int*)calloc(10,sizeof(int)); free(p); p = 0;

int * p = new int; delete p; p = 0;

int * p = new int[10]; delete[] p; p = 0;

Allocation de mémoire en C++

2 C A C++ VI

Page 18: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

double ** alloc_matrix(int n, int m) { double ** M = new double*[n];

for(int i=0; i< n; ++i) M[i] = new double[m];

return M; }

void free_matrix(double ** M, int n) { for(int i=0; i< n; ++i)

delete[] M[i]; delete[] M;

}

Page 19: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

La programmation orientée objet cherche à modéliser informatiquement des éléments du monde réel en entités informatiques appelées objets.

Les objets sont des données informatiques regroupant les principales caractéristiques des éléments du monde réel (taille, couleur, ...).

La difficulté du processus de modélisation est dans la création d'une représentation abstraite d'entités ayant une existence matérielle (chien, voiture, ampoule, ...) ou bien virtuelle (sécurité sociale, temps, ...).

2 C A C++ VII

Page 20: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Dans le monde réél, deux T-shirts peuvent être identique et distincts.

La classe , c'est la structure d'un objet, c'est-à-dire la déclaration de l'ensemble des entités qui composeront un objet. Une classe peut être considérée comme un moule à partir duquel on peut créer des objets.

Un objet est donc "issu" d'une classe. C'est une instanciation d'une classe, c'est la raison pour laquelle on pourra parler indifféremment d'objet ou d'instance.

Page 21: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Une classe est composée de deux parties:

•Les attributs (parfois appelés données membres): il s'agit des données représentant l'état de l'objet •Les méthodes (parfois appelées fonctions membres): il s'agit des opérations applicables aux objets

Si on définit la classe voiture, les objets Toyota_Civic, Mustang2003 seront des instanciations de cette classe. Il pourra éventuellement exister plusieurs objets Toyota_Civic, différenciés par leur numéro de série.

Deux instanciations de classes pourront même avoir tous leurs attributs égaux sans pour autant être le même objet.

Page 22: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Dans ce modèle, un véhicule est représenté par une chaîne de caractères (sa marque) et trois entiers : la puissance fiscale, la vitesse maximale et la vitesse courante.

chaque objet véhicule aura sa propre copie de ses données : on parle alors d'attribut d'instance. L'opération d'instanciation qui permet de créer un objet à partir d'une classe consiste précisément à fournir des valeurs particulières pour chacun des attributs d'instance.

Page 23: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572
Page 24: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

La déclaration de la classe commence par le mot clef class et est encadrée par une paire d'accolades. L'accolade finale est suivie d'un point virgule. Les membres déclarés après le mot clef public forment l'interface de la classe. Ceux qui suivent le mot private sont invisibles de l'utilisateur ;

L'ordre de déclaration des méthodes et des attributs est laissé au libre arbitre du programmeur.

La déclaration des attributs est semblable à la déclaration d'une variable alors que celle d'une méthode ressemble à s'y méprendre au prototype d'une fonction ! Néanmoins, il ne faut pas oublier que chaque méthode possède un argument caché : l'objet sur lequel elle est invoquée.

Page 25: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Lors de l'implémentation des méthodes, il est nécessaire de préfixer le nom de la méthode implémentée du nom de la classe suivi de '::'. Par exemple, l'implémentation de la méthode deplacerVers de la classe Point se fait en spécifiant:

Point::deplacerVers

Le constructeur est une méthode particulière qui porte le même nom que la classe et dont le but est d'initialiser les attributs lors de la création d'un objet.

Les méthodes x et y sont déclarées constantes à l'aide du mot clef const. Cela signifie que leur code n'affecte en aucune manière la valeur des attributs de l'objet cible.

Page 26: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

De la même manière, qu'une classe, un objet est caractérisé par:

• Attributs: Il s'agit des données caractérisant l'objet. Ce sont des variables stockant des informations d'état de l'objet

• Méthodes (appelées parfois fonctions membres): Les méthodes d'un objet caractérisent son comportement, c'est-à-dire l'ensemble des actions (appelées opérations) que l'objet est à même de réaliser. Ces opérations permettent de faire réagir l'objet aux sollicitations extérieures (ou d'agir sur les autres objets). De plus, les opérations sont étroitement liées aux attributs, car leurs actions peuvent dépendre des valeurs des attributs, ou bien les modifier

• De plus, un objet a aussi une Identitée

Page 27: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Encapsulation, polymorphism et héritage

•Encapsulation: •Le rassemblement des données et du code les utilisant dans une entité unique (objet). •La séparation nette entre la partie publique d'un objet (ou interface) seule connue de l'utilisateur de la partie privée ou implémentation qui reste masquée.

•Polymorphism: • Une méthode peut adopter plusieurs formes différentes.

•Héritage •Possibilité de définir des familles de classes traduisant le principe de généralisation / spécialisation. « La classe dérivée est une version spécialisée de sa classe de base »

Page 28: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

L'encapsulation consiste à masquer l'accès à certains attributs et méthodes d'une classe. Pourquoi masquer?

Cacher les détails d'implémentation des objets à l'utilisateur permet de modifier, par exemple la structure de données interne d'une classe (remplacer un tableau par une liste chaînée) sans pour autant entraîner de modifications dans le code de l’utilisateur, l’interface n’étant pas atteinte.

Abstraction de données : la structure d'un objet n'est pas visible de l'extérieur, son interface est constituée de messages invocables par un utilisateur. La réception d'un message déclenche l'exécution de la méthode correspondant à ce message.

Abstraction procédurale : Du point de vue de l'extérieur (c’est-à-dire en fait du client de l’objet), l'invocation d'un message est une opération atomique. L'utilisateur n'a aucun élément d'information sur la mécanique interne mise en œuvre. Par exemple, il ne sait pas si le traitement requis a demandé l’intervention de plusieurs méthodes ou même la création d’objets temporaires etc.

Encapsulation I

Page 29: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Encapsulation II

En C++, on choisit le paramètres d'encapsulation à l'aide des mots clés :

private : les membres privés ne sont accessibles que par les fonctions membres de la classe.

protected : les membres protégés sont comme les membres privés. Mais ils sont aussi accessibles par les fonctions membres des classes dérivées.

public : les membres publics sont accessibles par tous. La partie publique est appelée interface.

Les mots réservés private , protected et public peuvent figurer plusieurs fois dans la déclaration de la classe. Le droit d'accès ne change pas tant qu'un nouveau droit n'est pas spécifié.

Page 30: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

class Avion {

public : // fonctions membres publiques

void init(char [], char *, float); void affiche();

private : // membres privées

char immatriculation[6], *type; float poids;

// fonction membre privéevoid erreur(char *message);

}; // n'oubliez pas ce ; après l'accolade

Page 31: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

• Les fonctions membres sont définies dans un module séparé ou plus loin dans le code source.

• Syntaxe de la définition hors de la classe d'une méthode :

type Classe::nom_méthode( paramètres_formels ) {

// corps de la fonction

}

Page 32: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

class Avion {

public : // fonctions membres publiques

void init(char [], char *, float); void affiche();

private : // membres privées

char immatriculation[6], *type; float poids;

// fonction membre privéevoid erreur(char *message);

}; // n'oubliez pas ce ; après l'accolade

void Avion::init(char m[], char *t, float p) { if ( strlen(m) != 5 ) {

erreur("Immatriculation invalide"); strcpy( immatriculation, "?????");

} else

strcpy(immatriculation, m); type = new char [strlen(t)+1]; strcpy(type, t); poids = p;

}

void Avion::affiche() { cout << immatriculation << " " << type; cout << " " << poids << endl;

}

Page 33: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Comme pour struct , le nom de la classe représente un nouveau type de donnée.

On peut donc définir des variables de ce nouveau type; (créer des objets ou des instances)

Avion av1; // une instance simple (statique)

Avion *av2; // un pointeur (non initialisé)

Avion compagnie[10]; // un tableau d'instances

av2 = new Avion; // création (dynamique) d'une instance

Page 34: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Après avoir créé une instance (de façon statique ou dynamique) on peut accéder aux attributs et méthodes de la classe.

Cet accès se fait comme pour les structures à l'aide de l'opérateur . ou ->.

av1.init("FGBCD", "TB20", 1.47); av2->init("FGDEF", "ATR 42", 80.0); compagnie[0].init("FEFGH","A320", 150.0);

av1.affiche(); av2->affiche(); compagnie[0].affiche();

av1.poids = 0; // erreur, poids est un membre privé

Page 35: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

Certaines méthodes d'une classe ne doivent (ou ne peuvent) pas modifier les valeurs des données membres de la classe, ni retourner une référence non constante ou un pointeur non constant d'une donnée membre : on dit que ce sont des fonctions membres constantes.

Ce type de déclaration renforce les contrôles effectués par le compilateur et permet donc une programmation plus sûre sans coût d'exécution. Il est donc très souhaitable d'en déclarer aussi souvent que possible dans les classes.

class Nombre {

public : void setnbre(int n) {

nbre = n; }

// méthodes constantes int getnbre() const { return nbre; }

void affiche() const;

private : int nbre;

};

inline void Nombre::affiche() const { cout << "Nombre = " << nbre << endl;

}

Page 36: 2ième Classe (Mercredi, 13 Octobre) C++ Intro CSI2572

class vector { private:

double x,y; /* coordinate */ public:

vector(); /* default constructor: <0,0> */

vector(double, double); /* constructor: <x,y> */

double get_x() const; double get_y() const;

};

class line_segment {

private: vector a,b; /* end points */

public: line_segment(vector, vector); /* constructor: a,b */

vector get_a() const; vector get_b() const; void set_a(vector); void set_b(vector); vector middle() const;

};