Cours de C++ Guillaume Caumon, Février 2007 Introduction à la Programmation Orientée Objet.

Post on 03-Apr-2015

108 views 3 download

Transcript of Cours de C++ Guillaume Caumon, Février 2007 Introduction à la Programmation Orientée Objet.

Cours de C++Cours de C++

Guillaume Caumon, FGuillaume Caumon, Févrierévrier 2007 2007

Introduction Introduction àà la Programmation la Programmation OrientOrientéée Objete Objet

Le C++

IntroductionIntroduction

Du C au C++Du C au C++

Les ClassesLes Classes

L’héritageL’héritage

Programmation génériqueProgrammation générique

Pourquoi ce cours ?

Place importante de la modélisation en Geosciences :Place importante de la modélisation en Geosciences :- validation d’une théorie- validation d’une théorie- prédiction et calculs- prédiction et calculs- évaluation des risques- évaluation des risques

Les phénomènes étudiés sont complexesLes phénomènes étudiés sont complexes

La programmation orientée-objets peut faire gagner La programmation orientée-objets peut faire gagner beaucoup de tempsbeaucoup de temps

Objectif du cours

ConnaissanceConnaissance

TempsTemps

- Comprendre les concepts élémentaires de programmation Comprendre les concepts élémentaires de programmation orientée objet (POO)orientée objet (POO)- Etre capable de lire et comprendre du code C++Etre capable de lire et comprendre du code C++- Analyser un problème et le décomposer pour mieux le traiterAnalyser un problème et le décomposer pour mieux le traiter- Mettre en oeuvre les concepts de POO en langage C++ Mettre en oeuvre les concepts de POO en langage C++

Agenda

• Lundi pm : Du C au C++• Mardi am : exercices pratiques• Mardi pm : Les classes• Mercredi am : L’héritage• Mercredi pm : quizz et exercices• Jeudi am : exercices• Vendredi am : Bibliothèque std + exercices • Vendredi pm : colle (2h)

Bref historiqueL’algorithmique est une science ancienne (ex: algorithme

d’Euclide pour calculer le PGCD)

Mais la programmation une science nouvelle (ou un art nouveau ? [Knuth, the Art of Computer programming]).

- Métier à tisser de (1801): ancêtre des cartes perforées (Recencement 1890 - Brevet IBM 1930)

- Développement de programmes assembleur à partir des 40’s

pgcd(m, n) = pgcd(m − n, n) si m > npgcd(m, n) = pgcd(m, n − m) si m < n

Bref historique

Difficultés et erreurs

Développement de langages pour rendre le codage plus intuitif: Fortran (1950), ALGOL

Aujourd’hui:

- langages procéduraux (Pascal, C,…).

- langages fonctionnels (ML, CAML, …).

- langages orientés-objet (ADA, SmallTalk, Eiffel, C++, Java, …).

Qualité d’un Programme ?

1 Validit1 Validitéé Le programme fonctionneLe programme fonctionne

2 Extensibilit2 Extensibilitéé Je peux le faire évoluerJe peux le faire évoluer

3 R3 Rééutilisabilitutilisabilitéé Je peux utiliser des composantes Je peux utiliser des composantes du programme pour du programme pour d’autres applicationsd’autres applications

Comment s’y prendre ?

SSéparer le programme en modules réutilisableséparer le programme en modules réutilisables

Par analyse fonctionnelle descendantePar analyse fonctionnelle descendante

Par analyse ascendantePar analyse ascendante

UnitUnité fonctionelle autonome, é fonctionelle autonome, possédant une interfacepossédant une interfaceIndependante de son implantationIndependante de son implantation

(header.h)

(impl.cpp)

On peut le faire en C…

Modules = fonctions (déclaration / implementation)Modules = fonctions (déclaration / implementation)

Communication entre modules = appels de fonctionsCommunication entre modules = appels de fonctions

Flexibilité et réutilisation par des pointeurs de fonctionsFlexibilité et réutilisation par des pointeurs de fonctions

MAIS:MAIS:

- Les données sont globalesLes données sont globales

- Comprendre le programme équivaut à comprendre ce Comprendre le programme équivaut à comprendre ce que fait chaque fonctionque fait chaque fonction

Exemple C / C++ Calcul de distance

float hits[3][100]float x,y,z;int i = 0;float dist = 0;…for(i = 0; i < 100; i++ ){ x = hits[i][0]; y = hits[i][1]; z = hits[i][2]; dist = sqrt(x*x + y*y + z* z);}

Point points[100];Point orig(0, 0, 0);…

for( i = 0; i < 100; i++ ){ float dist = points[i].distance(origin);}

Changer les coordonnées de l’origine ?Changer les coordonnées de l’origine ?Passer en référentiel sphérique ?Passer en référentiel sphérique ?

Différences C / C++

Langages compilésLangages compilés

Analyse, mise en oeuvre et architecture des programmesAnalyse, mise en oeuvre et architecture des programmes

Possibilités de vérifications en C++ lors de la compilationPossibilités de vérifications en C++ lors de la compilation

C++ offre des nouvelles possibilitésC++ offre des nouvelles possibilités

La conception par objets

Cette mCette mééthode privilthode privilégie les données, égie les données, et non les fonctionset non les fonctions

Trouver les objets (physiques)Trouver les objets (physiques)

Décrire et classer les objetsDécrire et classer les objets

Implanter ces objetsImplanter ces objets

OpérationsOpérationsLiensLiensCaractéristiques communesCaractéristiques communes

Pourquoi concevoir des objets ?

Un être humain peut facilement comprendre Un être humain peut facilement comprendre simultanément un seul aspect d’un problèmesimultanément un seul aspect d’un problème

““Diviser pour régner”Diviser pour régner”

Associer les données et les fonctionnalitésAssocier les données et les fonctionnalités

Représenter des abstractionsReprésenter des abstractions

Recycler ces abstractionsRecycler ces abstractions

Un langage orienté objet

Permet:Permet:

La définition d’objets, avec partie publique et privéeLa définition d’objets, avec partie publique et privée

La modularité (compilation séparLa modularité (compilation séparéeée))

La réutilisation (mise en facteur des fonctionalités)La réutilisation (mise en facteur des fonctionalités)

L’extension des objets (héritage)L’extension des objets (héritage)

La lisibilité (distinction interface / implémentation)La lisibilité (distinction interface / implémentation)

La définition d’objets abstraitsLa définition d’objets abstraits

Exemple : les listes (code C)

typedef struct LIST {typedef struct LIST { NODE* p_first_node_ ;NODE* p_first_node_ ; NODE* p_last_node_ ;NODE* p_last_node_ ; int nb_items_ ;int nb_items_ ;} LIST ;} LIST ;

LIST* LIST_Create() ;LIST* LIST_Create() ;void LIST_Destroyvoid LIST_DestroyBOOLEAN LIST_Owns_ItemBOOLEAN LIST_Owns_Item

typedef struct NODE {typedef struct NODE { struct NODE* next_ ;struct NODE* next_ ; void* p_item_ ;void* p_item_ ;} NODE ;} NODE ;

……

() ;() ;() ;() ;

( LIST* p_list ) ;( LIST* p_list ) ; ( ( LIST* p_list, PNTR* itemLIST* p_list, PNTR* item) ;) ;……

Plus explicite… Mais le compilateur C ne peut Plus explicite… Mais le compilateur C ne peut pas vérifier les typespas vérifier les types

Exemple : les listes (code C)typedef struct DATA {typedef struct DATA { int index_;int index_; char value_;char value_;} DATA;} DATA;

BOOLEAN check_item( LIST* list, DATA* data ) {BOOLEAN check_item( LIST* list, DATA* data ) { BOOLEAN found = LIST_Owns_Item( list, data );BOOLEAN found = LIST_Owns_Item( list, data ); if( found ) {if( found ) { printf( printf( “ “Item %d , %c in List”, Item %d , %c in List”, data->index_, data->value_data->index_, data->value_ );); }} return found;return found;}} Problème: Une fonction par type de donnée…Problème: Une fonction par type de donnée…

Exemple : les listes (code C++)class Node {class Node {……};};

class List {class List {public :public : List();List(); ~List();~List(); bool owns_item( void* item ) const;bool owns_item( void* item ) const;private :private : Node* first_node_ ;Node* first_node_ ; Node* last_node_ ;Node* last_node_ ; int nb_items_ ;int nb_items_ ;};};

Exemple : les listes (code C++)class Data {class Data {public :public : Data( int index, char value );Data( int index, char value ); void print() const;void print() const;private :private : int ind_;int ind_; char val_;char val_;};};bool check_item( List* list, Data* data ) {bool check_item( List* list, Data* data ) { bool found = list->owns_item( data );bool found = list->owns_item( data ); if( found ) {if( found ) { data->print();data->print(); }} return found;return found;}}

HistoriqueCréé par B. Stroustrup (Bell Labs. ) à partir de 1979Créé par B. Stroustrup (Bell Labs. ) à partir de 1979(“C with classes”).(“C with classes”).Initialement: code C++ précompilé Initialement: code C++ précompilé → code C→ code CDevient public en 1985 sous le nom de C++.Devient public en 1985 sous le nom de C++.La version normalisée (ANSI) paraît en 1996.La version normalisée (ANSI) paraît en 1996.

C++ = C +C++ = C +

Vérifications de type + stricteVérifications de type + stricteSurcharge de fonctionsSurcharge de fonctionsOpérateursOpérateursRéférencesRéférencesGestion mémoire + facileGestion mémoire + facileEntrées/sorties + facileEntrées/sorties + facileClasses et héritageClasses et héritageProgrammation génériqueProgrammation générique……

Un langage compilé…

Langage = protocole de communication entre Langage = protocole de communication entre le programmeur et le processeur.le programmeur et le processeur.

Code C/C++Code C/C++

Code pré-processéCode pré-processé

ProgrammeProgramme

LibrairiesLibrairies

Fichier(s) ObjetFichier(s) Objet

Le C++

HistoriqueHistorique

Du C au C++Du C au C++

Les ClassesLes Classes

L’héritageL’héritage

Programmation génériqueProgrammation générique

Commentaires

C /* This is a multi-line

C comment */

C++ /* This is just

the same in C++, but… */

// … We also have single-line comments

Règles : • rester cohérent• appliquer une norme pour générer de la doc html automatiquement.

Prototypes de fonctions

// declaration in a header file.// declaration in a header file.void function( int param1, int param2 = 10 );void function( int param1, int param2 = 10 );

header.h

// implementation file// implementation filevoid function( int param1, int param2 ) {void function( int param1, int param2 ) {

// print ‘param1’ and ‘param2’ to // print ‘param1’ and ‘param2’ to // the standard output.// the standard output.

}}

impl.cpp

// main function// main functionint main( int argc, char** argv ) {int main( int argc, char** argv ) {

function( 5, 3 );function( 5, 3 );function( 5 );function( 5 );return 0;return 0;

}}

client.cpp

SurchargeSurcharge de fonctionsSurcharge de fonctions

int square( int value );int square( int value );float square( float value );float square( float value );double square( double value );double square( double value );

header.h

Surcharge d’opérateursSurcharge d’opérateurstypedef struct Complex {typedef struct Complex {

float x_;float x_;float y_;float y_;

};};Complex& operator+(Complex& operator+( Complex& lhs,Complex& lhs, const Complex& rhs const Complex& rhs ););

complex.h

Utilisation de Utilisation de ComplexComplex comme d’un type standard comme d’un type standard

Surcharge

• Les types des paramètres peuvent être utilisés pour la surchage, mais pas la valeur de retour.

double square( double value );double square( double value );float square( double value );float square( double value );

Erreur de compilationErreur de compilation

Fonctions inlines

// declaration// declarationinline bool max( int x, int y );inline bool max( int x, int y );

// implementation// implementationinline int max( int x, int y ) {inline int max( int x, int y ) {

return (x > y) ? x : y;return (x > y) ? x : y;}}

header.h

// preprocessor macro// preprocessor macro#define MAX(x,y) (x > y) ? x : y;#define MAX(x,y) (x > y) ? x : y;

Fonctions inlines

void client_function( int a, int b ) {void client_function( int a, int b ) { inf c = 0;inf c = 0; if( … ) c = MAX(a+=a, b+=b); if( … ) c = MAX(a+=a, b+=b); // preproc macro// preproc macro

else c = max(a+=a, b+=b); else c = max(a+=a, b+=b); // inline function// inline function

//…//…}}

client.cpp

void client_function( int a, int b ) {void client_function( int a, int b ) { int c = 0;int c = 0; if( … ) c = (a+=a > b+=b) ? a+=a : b+=b;if( … ) c = (a+=a > b+=b) ? a+=a : b+=b; else { a += a; b += b;else { a += a; b += b; c = (a > b) ? a : b;c = (a > b) ? a : b; //…//…}}

Equivalent client.cpp

Déclaration de variables

C++ permet de déclarer des variables C++ permet de déclarer des variables n’importe où et de les initialiser.n’importe où et de les initialiser.

Règles:Règles:• toujours déclarer ses variables au dernier toujours déclarer ses variables au dernier moment.moment.• initialiser TOUTES les variables.initialiser TOUTES les variables.• déclarer une variable par ligne.déclarer une variable par ligne.

Constancechar* c1; Pointeur variable vers une

chaîne de caractères variable.

const char* c2; Pointeur variable vers une chaîne de caractères constante.

char* const c3; Pointeur constant vers une chaîne de caractères variable.

const char* const c4; Pointeur constant vers une chaîne de caractères constante.

Références

Pointeurs Référencesint array[10];

int* pointer =

&array[5];

int value = *pointer;

*pointer = 100;

int array[10];

int& ref = array[5];

int value = ref;

ref = 100;

Peut changer au cours du temps

Ne peut pas changer d’objet

Peut être nul Référence toujours une variable valide, définie lors de la déclaration de la référence

Références

Pointeurs Référencesint a = 10;

int* const p = &a;

int a = 10;

int& r = &a;

RRééférence férence pointeur non nul qui indique pointeur non nul qui indique toujours la meme adressetoujours la meme adresse

Conséquence : ne pas utiliser des T* const mais Conséquence : ne pas utiliser des T* const mais des T&, c’est plus élégant.des T&, c’est plus élégant.

Allocation mémoire

C int value = 10;

int* var = (int*)malloc(sizeof(int));

*var = value;

int* array = (int*)malloc(n*sizeof(int));

C++ int value = 10;

int* var = new int( value );

int* array = new int[10];

En C++, les allocations sont typées.

Désallocation mémoire

C int* var = (int*)malloc(sizeof(int));

int* array = (int*)malloc(n*sizeof(int));

free( var );

free( array );

C++ int* var = new int();

int* array = new int[10];

delete var;

delete [] array;

CC C++C++#include <#include <stdio.hstdio.h>> #include <#include <iostreamiostream>>

#include <f#include <fstreamstream>>#include <str#include <strstreamstream>>

printf --> standard outputprintf --> standard output

scanf <-- standard inputscanf <-- standard inputfprintf --> FILEfprintf --> FILE**fscanf <-- FILE*fscanf <-- FILE*sprintf --> char[N]sprintf --> char[N]sscanf <-- char*[N]sscanf <-- char*[N]

cout --> standard outputcout --> standard outputcerr --> standard error cerr --> standard error outputoutputcin <-- standard inputcin <-- standard inputofstream --> output fileofstream --> output fileifstream <-- input fileifstream <-- input fileostringstream --> char*[N]ostringstream --> char*[N]istringstream <-- char*[N]istringstream <-- char*[N]

ostream& operator<<ostream& operator<<istream& operator>>istream& operator>>

Entrées / Sorties (I)

Entrées / Sorties (II)C #include <stdio.h>

int value = 10;

printf( “value = %d\n”, value );

printf( “New value = ??\n” );

scanf( “%d”, &value );

C++ #include <iostream>

using namespace std;

int value = 10;

cout << “Value = “ << value << endl;

cout << “New value = ?? ” << endl;

cin >> value;

Les opérateurs ‘<<‘ et ‘>>’ sont surchargeables.

Entrées / Sorties (III)

C #include <stdio.h>

FILE* file;

if( fopen( file, “filename” ) ) {

fprintf( file, “Hello!!\n” );

}

C++ #include <fstream>

using namespace std;

ofstream outfile( “filename” );

if( outfile.good() ) {

outfile << “Hello!!” << endl;

}

Entrées / Sorties (IV)

typedef struct Complex {typedef struct Complex { float x_;float x_; float y_;float y_;} Complex;} Complex;

using namespace std;using namespace std;ostream& operator<<(ostream& operator<<( ostream& os, const Complex& zostream& os, const Complex& z) {) { return os << z.x_ << " + “return os << z.x_ << " + “ << z.y_ << << z.y_ << “ “ * * ii";";}}

Le C++

HistoriqueHistorique

Du C au C++Du C au C++

Les ClassesLes Classes

L’héritageL’héritage

Programmation génériqueProgrammation générique

Fonctions et structures

struct Date {struct Date { int year_;int year_; int month_;int month_; int day_;int day_; void print();void print();};};

file.h

file.cppvoid Date::print() {void Date::print() { cout << month_ << “/” cout << month_ << “/” << day_ << “/” << year_ << endl;<< day_ << “/” << year_ << endl;}}

Classe C++ : interface

/**/** * A calendar date.* A calendar date. */*/

class Date {class Date {public :public : void set_date( void set_date( int year, int month, int dayint year, int month, int day );); void print() const;void print() const;

private :private : int year_;int year_; int month_;int month_; int day_;int day_;};};

file.h

Classe C++ : implantation

file.cppvoid Date::set_date(void Date::set_date( int year, int month, int dayint year, int month, int day) {) { if( if( month == 2month == 2 && ! bisextile( year )&& ! bisextile( year ) && day > 28&& day > 28 ) {) { cerr << “Where did you see that\n”cerr << “Where did you see that\n” << “February could have “ << “February could have “ << day << “ days “<< day << “ days “ << “in “ << year << “!” << endl;<< “in “ << year << “!” << endl; }} // etc. // etc. }}

Constructeurs / Destructeurs

class Date {class Date {public :public : /**/** * Creates a Date from the year, month and day.* Creates a Date from the year, month and day. * if parameters are not consistent, an error* if parameters are not consistent, an error * message is produced.* message is produced.

*/*/

Date( int year, int month, int day );Date( int year, int month, int day ); /** Copy constructor *//** Copy constructor */

Date( const Date& other_date );Date( const Date& other_date ); /** Destroys this Date *//** Destroys this Date */

~Date();~Date(); // …// …};};

file.h

Constructeurs / Destructeurs

file.cppDate::Date(Date::Date( int year, int month, int dayint year, int month, int day) {) { set_date( year, month, day );set_date( year, month, day );}}

Date::Date( const Date& other ) :Date::Date( const Date& other ) : year_( other.year_ ),year_( other.year_ ), month_( other.month_ ),month_( other.month_ ), day_( other.day_ ) {day_( other.day_ ) {}}

Date::~Date() {Date::~Date() { // nothing to do// nothing to do}}

Constructeur par copie ou ‘=‘ ?

void printperson( const Person& p ) {void printperson( const Person& p ) { Person tmp;Person tmp; tmp = p;tmp = p; cout << "Name: " << tmp.get_name() cout << "Name: " << tmp.get_name() << ", date of birth: " << ", date of birth: " << tmp.get_date_of_birth << endl;<< tmp.get_date_of_birth << endl;} }

void printperson( const Person& p ) {void printperson( const Person& p ) { Person tmpPerson tmp( p )( p );; cout << "Name: " << tmp.get_name() cout << "Name: " << tmp.get_name() << ", date of birth: " << ", date of birth: " << tmp.get_date_of_birth() << endl;<< tmp.get_date_of_birth() << endl;} }

file.cpp

Fonctions constantes

class Date {class Date {public :public : // …// … /** /** * Prints this date to the standard output.* Prints this date to the standard output. * Format is American: mm/dd/yy* Format is American: mm/dd/yy */*/

void print() const;void print() const; // …// …};};

file.h

file.cppvoid Date::print() const {void Date::print() const { cout << month_ << “/” cout << month_ << “/” << day_ << “/” << year_ << endl;<< day_ << “/” << year_ << endl;}}

Variables statiques

class Date {class Date {public :public : // …// … /** To be called once in the program *//** To be called once in the program */

static void init();static void init();private :private : static bool bisextile( int year );static bool bisextile( int year ); static int nb_days(static int nb_days( int month, int yearint month, int year ););

private :private : static int nb_days_per_month_[12];static int nb_days_per_month_[12];};};

file.h

Classes imbriquées

class Triangle {class Triangle {public :public : //…//…

class Edge {class Edge { public :public : //…//… Triangle* incident_triangle(Triangle* incident_triangle( int indexint index );); };};};};

file.h

Relations entre classes

class Object {class Object {public :public : //…//…private :private : ObjectUpdater* updater_;ObjectUpdater* updater_;};};

class ObjectUpdater {class ObjectUpdater {public :public : //…//…private :private : Object* object_;Object* object_;};};

file.h

Relations entre classes

class ObjectUpdater;class ObjectUpdater;class Object {class Object {public :public : //…//…private :private : ObjectUpdater* updater_;ObjectUpdater* updater_;};};

class ObjectUpdater {class ObjectUpdater {public :public : //…//…private :private : Object* object_;Object* object_;};};

file.h

Le C++

HistoriqueHistorique

Du C au C++Du C au C++

Les ClassesLes Classes

L’héritageL’héritage

Programmation génériqueProgrammation générique

Règles d’héritage

““Une voiture Une voiture est unest un véhicule”véhicule”

VehicleVehicle

CarCar

class Vehicle {class Vehicle { //… //… };};

class Car : public Vehicle {class Car : public Vehicle { //…//…};};

file.h

Exemple

CircleCircle SquareSquareLineLineGeomFigurGeomFiguree

GeomShapeGeomShape

Conversions et classes parentes

BaseBase

DerivedDerived

Base y; Derived y;

Base& x = y;

Derived& x = y;

OKOK

NONNON

OKOK

OKOK

Construire une classe dérivée

class Vehicle {class Vehicle {public :public : Vehicle();Vehicle();};};

class Car : public Vehicle {class Car : public Vehicle {public :public : Car();Car();};};

file.h

file.cppCar::Car() : Vehicle() {Car::Car() : Vehicle() {}}

public, protected, private

public : accessible par tous

protected : accessible uniquement par les classes dérivées

private : fonctionnement interne à la classe

Surcharge de fonctionsclass Vehicle {class Vehicle {public :public : float power() const; // returns 0float power() const; // returns 0};};class Car : public Vehicle {class Car : public Vehicle {public :public : float power() const; // returns 100float power() const; // returns 100};};

file.h

int main( int argc, char** argv ) {int main( int argc, char** argv ) {Vehicle v;Vehicle v;cout << v.power() << endl;cout << v.power() << endl;Car c;Car c;cout << c.power() << endl;cout << c.power() << endl;Vehicle& v2 = c;Vehicle& v2 = c;cout << v2.power() << endl;cout << v2.power() << endl;return 0;return 0;

}}

file.cpp

Expérience (I)class Employee {class Employee {public :public : float income();float income(); // 1000 // 1000 char* name();char* name();};};

class Boss : public Employee {class Boss : public Employee {public :public : float income();float income(); // 10000 // 10000};};

class Company {class Company {public :public : void print_all_incomes();void print_all_incomes(); void add_employee( Employee* employee );void add_employee( Employee* employee );prprivateivate : : Employee** employees_;Employee** employees_; int nb_employees_;int nb_employees_;}; };

CompanyCompany

BossBoss

EmployeeEmployee

Expérience (II)

int main( int argc, char** argv ) {int main( int argc, char** argv ) {

Company company(3);Company company(3); Boss* homer = new Boss( "Homer" );Boss* homer = new Boss( "Homer" ); company.add_employee( homer );company.add_employee( homer ); Employee* marge = new Employee( "Marge" );Employee* marge = new Employee( "Marge" ); company.add_employee( marge );company.add_employee( marge ); Employee* bart = new Employee( "Bart" );Employee* bart = new Employee( "Bart" ); company.add_employee( bart );company.add_employee( bart );

company.print_all_incomes();company.print_all_incomes(); return 1; return 1; }}

file.cpp

Expérience (III)

void Company::print_all_incomes() {void Company::print_all_incomes() { for( int i = 0; i < nb_employees_; ++i )for( int i = 0; i < nb_employees_; ++i ) { { cout << employees_[i]->name()cout << employees_[i]->name() << ": " << employees_[i]->income()<< ": " << employees_[i]->income() << endl;<< endl; } } }}

file.cpp

Solution : fonctions virtuelles

class Employee {class Employee {public :public : virtualvirtual float income();float income(); // 1000 // 1000 char* name();char* name();};};

class Boss : public Employee {class Boss : public Employee {public :public : virtual virtual float income();float income(); // 10000 // 10000};};

CompanyCompany

BossBoss

EmployeeEmployee

Exerciceclass Base { class Base { public :public : virtual void f1();virtual void f1(); virtual void f2();virtual void f2();};};

obj->f1() obj->f2() obj->f3()

Base* obj = new Base;

Base* obj = new Derived;

Derived* obj = new Base;

Derived* obj = new Derived;

class Derived : public Base {class Derived : public Base {public : public : virtual void f2(); virtual void f2(); virtual void f3(); virtual void f3(); }; };

Mécanisme du polymorphisme

BaseBase

DerivedDerived

Base::vf1Base::vf1

Base::vf2Base::vf2

Base::vf3Base::vf3

Derived::vf1Derived::vf1

Derived::vf3Derived::vf3

vtbl_vtbl_

BaseBasevtbl_vtbl_

Dérivation et destruction

Une classe de base doit Une classe de base doit toujourstoujours avoir avoir un destructeur virtuel.un destructeur virtuel.

class Vehicle {class Vehicle {public :public : virtual ~Vehicle();virtual ~Vehicle();};};

class Car : public Vehicle {class Car : public Vehicle {public :public : virtual ~Car();virtual ~Car();};};

file.h

Construire / Detruire

BaseBase

DerivedDerivedAppel desAppel desconstructeursconstructeurs

Appel desAppel desdestructeursdestructeurs

Règles :Règles :• Ne jamais appeler une fonction virtuelle Ne jamais appeler une fonction virtuelle dans un constructeur.dans un constructeur.• Une fonction virtuelle ne peut pas etre Une fonction virtuelle ne peut pas etre inlineinline•Toujours utiliser des pointeurs / Toujours utiliser des pointeurs / références pour utiliser le polymorphisme.références pour utiliser le polymorphisme.

Objets virtuels purs

Une classe de base peut définir des Une classe de base peut définir des fonctions sans les implanter.fonctions sans les implanter.Elle force ainsi l’implantation dans ses Elle force ainsi l’implantation dans ses classes dérivées.classes dérivées.

class Vehicle {class Vehicle {public :public : virtual ~Vehicle();virtual ~Vehicle(); virtual float power() const = 0;virtual float power() const = 0;

protected :protected : Vehicle();Vehicle();};};

file.h

Philosophie de l’Héritage

Héritage public Héritage public ‘est un’ ‘est un’

En d’autres termes:En d’autres termes:Ce qui s’applique a une classe de Ce qui s’applique a une classe de

base s’applique a ses classes dérivées.base s’applique a ses classes dérivées.

Question: une classe Question: une classe CarreCarre peut-elle deriver d’une peut-elle deriver d’une classe classe RectangleRectangle ??

Reponse : non ! Ce qui est vrai pour un rectangle Reponse : non ! Ce qui est vrai pour un rectangle n’est pas vrai pour un carre. n’est pas vrai pour un carre.

Philosophie de l’Héritage

Héritage de l’interface

Héritage de l’implantation

Fonction non virtuelle

Obligatoire Obligatoire

Fonction virtuelle

Obligatoire Par défaut, possibilité de redéfinir

Fonction virtuelle pure

Obligatoire Non, à redéfinir

Le C++

HistoriqueHistorique

Du C au C++Du C au C++

Les ClassesLes Classes

L’héritageL’héritage

Programmation génériqueProgrammation générique

Paramétrer des classes…

Cas d’une liste chaînée: les objets de la liste Cas d’une liste chaînée: les objets de la liste peuvent etre de type différent.peuvent etre de type différent. ( (void*void*))

template<class T> class List {template<class T> class List {public :public : List( int nb_items );List( int nb_items ); ~List();~List();

void append_item( const T& item );void append_item( const T& item ); void remove_item( const T& item );void remove_item( const T& item ); void remove_all();void remove_all(); //…//…};};

file.h

… ou des fonctions/**/** * Swaps two objects of type T.* Swaps two objects of type T. * T should provide copy constructor* T should provide copy constructor * and operator=* and operator= */*/

template<class T> void swap(template<class T> void swap( T& t1, T& t2T& t1, T& t2););

file.h

template<class T> void swap(template<class T> void swap( T& t1, T& t2T& t1, T& t2) {) { T tmp(t1);T tmp(t1); t1 = t2;t1 = t2; t2 = tmp;t2 = tmp;}}

file.h

Les templates

Le code template n’est compilé que lors de Le code template n’est compilé que lors de l’instanciation. l’instanciation.

On peut utiliser ‘On peut utiliser ‘typenametypename’ (ANSI), ’ (ANSI), ‘‘classclass’ ou ‘’ ou ‘intint’ comme arguments ’ comme arguments templates.templates.

On peut imposer des fonctions aux On peut imposer des fonctions aux arguments templates.arguments templates.

Exemple

template <class T> class List {template <class T> class List { //…//…};};

/**/** * Sorts a List of objects of type T.* Sorts a List of objects of type T. * T must provide operators <* T must provide operators < */*/

template <class T> class ListSorter {template <class T> class ListSorter {public :public : ListSorter( List<T>& list );ListSorter( List<T>& list ); void sort();void sort();private :private : List<T>& list_;List<T>& list_;};};

file.h

Programmation Générique

Idée:Idée:

Remplacer les fonctions virtuelles par Remplacer les fonctions virtuelles par des spécifications d’arguments des spécifications d’arguments templates…templates…

Conclusions

• Quelques heures pour apprendre le C++ … C’est peu !!!– Gestion des exceptions– Amitié entre objets– Standard Template Library– ANSI C++– Pratique

Références

• Brokken et Kubat, C++ Annotations, http://www.icce.rug.nl/docs/cpp.shtml

• Stroustrup, Le langage C++ (3e ed.), Addisson Wesley, 1996.

• Gamma et al., Design Patterns, Addisson Wesley, 1995.

• Meyers, Effective C++, Addisson Wesley.• Gautier et al., Cours de Programmation

par objets, Masson.