Vous êtes sur la page 1sur 76

Introduction la Programmation Orient Objet e

Cours de C++

Guillaume Caumon, Fvrier 2007

Le C++
Introduction Du C au C++ Les Classes Lhritage Programmation gnrique

Pourquoi ce cours ?
Place importante de la modlisation en Geosciences : - validation dune thorie - prdiction et calculs - valuation des risques

Les phnomnes tudis sont complexes La programmation oriente-objets peut faire gagner beaucoup de temps

Objectif du cours
- Comprendre les concepts lmentaires de programmation oriente objet (POO) - Etre capable de lire et comprendre du code C++ - Analyser un problme et le dcomposer pour mieux le traiter - Mettre en oeuvre les concepts de POO en langage C++ Connaissance

Temps

Agenda
Lundi pm : Du C au C++ Mardi am : exercices pratiques Mardi pm : Les classes Mercredi am : Lhritage Mercredi pm : quizz et exercices Jeudi am : exercices Vendredi am : Bibliothque std + exercices Vendredi pm : colle (2h)

Bref historique
Lalgorithmique est une science ancienne (ex: algorithme d Euclide pour calculer le PGCD) pgcd(m, n) = pgcd(m n, n) si m > n pgcd(m, n) = pgcd(m, n m) si m < n Mais la programmation une science nouvelle (ou un art nouveau ? [Knuth, the Art of Computer programming]). - Mtier tisser de (1801): anctre des cartes perfores (Recencement 1890 - Brevet IBM 1930) - Dveloppement de programmes assembleur partir des 40s

Bref historique
Difficults et erreurs Dveloppement de langages pour rendre le codage plus intuitif: Fortran (1950), ALGOL Aujourdhui: - langages procduraux (Pascal, C,). - langages fonctionnels (ML, CAML, ). - langages orients-objet (ADA, SmallTalk, Eiffel, C++, Java, ).

Qualit dun Programme ?


1 Validit 2 Extensibilit 3 Rutilisabilit Le programme fonctionne Je peux le faire voluer Je peux utiliser des composantes du programme pour dautres applications

Comment sy prendre ?
Sparer le programme en modules rutilisables Unit fonctionelle autonome, possdant une interface (header.h) (impl.cpp) Independante de son implantation Par analyse fonctionnelle descendante Par analyse ascendante

On peut le faire en C
Modules = fonctions (dclaration / implementation) Communication entre modules = appels de fonctions Flexibilit et rutilisation par des pointeurs de fonctions MAIS: - Les donnes sont globales - Comprendre le programme quivaut comprendre ce que 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 coordonnes de lorigine ? Passer en rfrentiel sphrique ?

Diffrences C / C++
Langages compils Analyse, mise en oeuvre et architecture des programmes Possibilits de vrifications en C++ lors de la compilation C++ offre des nouvelles possibilits

La conception par objets


Cette mthode privilgie les donnes, et non les fonctions Trouver les objets (physiques) Dcrire et classer les objets Oprations Liens Caractristiques communes Implanter ces objets

Pourquoi concevoir des objets ?


Un tre humain peut facilement comprendre simultanment un seul aspect dun problme Diviser pour rgner Associer les donnes et les fonctionnalits Reprsenter des abstractions Recycler ces abstractions

Un langage orient objet


Permet: La dfinition dobjets, avec partie publique et prive La lisibilit (distinction interface / implmentation) La modularit (compilation spare) La rutilisation (mise en facteur des fonctionalits) Lextension des objets (hritage) La dfinition dobjets abstraits

Exemple : les listes (code C)


typedef struct LIST { NODE* p_first_node_ ; NODE* p_last_node_ ; int nb_items_ ; typedef struct NODE { } LIST ; struct NODE* next_ ; void* p_item_ ; } NODE ; LIST* LIST_Create() ; ( ; void LIST_Destroy()LIST* p_list ) ; ( BOOLEAN LIST_Owns_Item () ; LIST* p_list, PNTR* item ) ; Plus explicite Mais le compilateur C ne peut pas vrifier les types

Exemple : les listes (code C)


typedef struct DATA { int index_; char value_; } DATA;

BOOLEAN check_item( LIST* list, DATA* data ) { BOOLEAN found = LIST_Owns_Item( list, data ); if( found ) { printf( Item %d , %c in List, data->index_, data->value_ ); } return found; } Problme: Une fonction par type de donne

Exemple : les listes (code C++)


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

Exemple : les listes (code C++)


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

Historique
Cr par B. Stroustrup (Bell Labs. ) partir de 1979 (C with classes). Initialement: code C++ prcompil code C Devient public en 1985 sous le nom de C++. La version normalise (ANSI) parat en 1996. Vrifications de type + stricte Surcharge de fonctions Oprateurs Rfrences Gestion mmoire + facile Entres/sorties + facile Classes et hritage Programmation gnrique

C++ = C +

Un langage compil
Langage = protocole de communication entre le programmeur et le processeur.
Code C/C++ Code pr-process Librairies Fichier(s) Objet Programme

Le C++
Historique Du C au C++ Les Classes Lhritage Programmation gnrique

Commentaires
C
/* This is a multi-line C comment */

C++ /* This is just


the same in C++, but */ // We also have single-line comments

Rgles : rester cohrent appliquer une norme pour gnrer de la doc html automatiquement.

Prototypes de fonctions
header.h // declaration in a header file. void function( int param1, int param2 = 10 ); impl.cpp // implementation file void function( int param1, int param2 ) { // print param1 and param2 to // the standard output. } client.cpp // main function int main( int argc, char** argv ) { function( 5, 3 ); function( 5 ); return 0; }

Surcharge de fonctions

Surcharge
header.h

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

Surcharge doprateurs
typedef struct Complex { float x_; float y_; }; Complex& operator+( Complex& lhs, const Complex& rhs ); complex.h

Utilisation de Complex comme dun type standard

Surcharge
Les types des paramtres peuvent tre utiliss pour la surchage, mais pas la valeur de retour.
double square( double value ); float square( double value );

Erreur de compilation

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

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

header.h

// implementation inline int max( int x, int y ) { return (x > y) ? x : y; }

Fonctions inlines
client.cpp void client_function( int a, int b ) { inf c = 0; if( ) c = MAX(a+=a, b+=b); // preproc macro else c = max(a+=a, b+=b); // inline function // } Equivalent client.cpp void client_function( int a, int b ) { int c = 0; if( ) c = (a+=a > b+=b) ? a+=a : b+=b; else { a += a; b += b; c = (a > b) ? a : b; // }

Dclaration de variables
C++ permet de dclarer des variables n importe o et de les initialiser. Rgles:
toujours dclarer ses variables au dernier moment. initialiser TOUTES les variables. dclarer une variable par ligne.

Constance
Pointeur variable vers une chane de caractres variable. const char* c2; Pointeur variable vers une chane de caractres constante. char* const c3; Pointeur constant vers une chane de caractres variable. const char* const c4; Pointeur constant vers une chane de caractres constante.
char* c1;

Rfrences
Pointeurs
int array[10]; int* pointer = &array[5]; int value = *pointer; *pointer = 100;

Rfrences
int array[10]; int& ref = array[5]; int value = ref; ref = 100;

Peut changer au cours du temps Peut tre nul

Ne peut pas changer d objet Rfrence toujours une variable valide, dfinie lors de la dclaration de la rfrence

Rfrences
Pointeurs
int a = 10; int* const p = &a;

Rfrences
int a = 10; int& r = &a;

Rfrence pointeur non nul qui indique toujours la meme adresse Consquence : ne pas utiliser des T* const mais des T&, cest plus lgant.

Allocation mmoire
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 types.

Dsallocation mmoire
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;

Entres / Sorties (I)


C
#include <stdio.h>

C++
#include <iostream> #include <fstream> #include <strstream>

printf --> standard output cout --> standard output cerr --> standard error output scanf <-- standard input cin <-- standard input fprintf --> FILE* ofstream --> output file fscanf <-- FILE* ifstream <-- input file sprintf --> char[N] ostringstream --> char*[N] sscanf <-- char*[N] istringstream <-- char*[N] ostream& operator<< istream& operator>>

Entres / 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 oprateurs << et >> sont surchargeables.

Entres / 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; }

Entres / Sorties (IV)


typedef struct Complex { float x_; float y_; } Complex; using namespace std; ostream& operator<<( ostream& os, const Complex& z ) { return os << z.x_ << " + << z.y_ << * i"; }

Le C++
Historique Du C au C++ Les Classes Lhritage Programmation gnrique

Fonctions et structures
struct Date { int year_; int month_; int day_; void print(); }; file.h

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

Classe C++ : interface


/** * A calendar date. */

file.h

class Date { public : void set_date( int year, int month, int day ); void print() const; private int int int }; : year_; month_; day_;

Classe C++ : implantation


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

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

Date( int year, int month, int day );


/** Copy constructor */

Date( const Date& other_date );


/** Destroys this Date */

~Date(); // };

Constructeurs / Destructeurs
Date::Date( int year, int month, int day ) { set_date( year, month, day ); } Date::Date( const Date& other ) : year_( other.year_ ), month_( other.month_ ), day_( other.day_ ) { } Date::~Date() { // nothing to do } file.cpp

Constructeur par copie ou = ?


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

Fonctions constantes
class Date { public : // file.h

/** * Prints this date to the standard output. * Format is American: mm/dd/yy */

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

Variables statiques
class Date { public : // file.h

/** To be called once in the program */

static void init(); private : static bool bisextile( int year ); static int nb_days( int month, int year ); private : static int nb_days_per_month_[12]; };

Classes imbriques
class Triangle { public : // file.h

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

Relations entre classes


class Object { public : // private : ObjectUpdater* updater_; }; class ObjectUpdater { public : // private : Object* object_; }; file.h

Relations entre classes


class ObjectUpdater; class Object { public : // private : ObjectUpdater* updater_; }; class ObjectUpdater { public : // private : Object* object_; }; file.h

Le C++
Historique Du C au C++ Les Classes Lhritage Programmation gnrique

Rgles dhritage
Vehicle Une voiture vhicule est un Car
file.h

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

Exemple
GeomShape

GeomFigur e

Line

Circle

Square

Conversions et classes parentes


Base Derived Base y; Base& x = y; Derived& x = y; Derived y;

OK NON

OK OK

Construire une classe drive


class Vehicle { public : Vehicle(); }; class Car : public Vehicle { public : Car(); }; Car::Car() : Vehicle() { } file.cpp file.h

public, protected, private


public : accessible par tous

protected :

accessible uniquement par les classes drives fonctionnement interne la classe

private :

Surcharge de fonctions
class Vehicle { public : float power() const; // returns 0 }; class Car : public Vehicle { public : float power() const; // returns 100 }; int main( int argc, char** argv ) { Vehicle v; cout << v.power() << endl; Car c; cout << c.power() << endl; Vehicle& v2 = c; cout << v2.power() << endl; return 0; } file.h

file.cpp

Exprience (I)
class Employee { Company public : float income(); // 1000 char* name(); }; class Boss : public Employee { public : float income(); // 10000 }; class Company { public : void print_all_incomes(); void add_employee( Employee* employee ); private : Employee** employees_; int nb_employees_; };

Employee Boss

Exprience (II)
int main( int argc, char** argv ) {
file.cpp

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

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

Solution : fonctions virtuelles


Company Employee Boss

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

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

obj->f1() Base* obj = new Base; Base* obj = new Derived; Derived* obj = new Base; Derived* obj = new Derived;

obj->f2()

obj->f3()

Mcanisme du polymorphisme
Base
vtbl_

Base::vf1 Base::vf2 Base::vf3

Derived Base
vtbl_

Derived::vf1 Derived::vf3

Drivation et destruction
Une classe de base doit un destructeur virtuel.
class Vehicle { public : virtual ~Vehicle(); }; class Car : public Vehicle { public : virtual ~Car(); };

toujours avoir

file.h

Construire / Detruire
Base
Appel des constructeurs Appel des destructeurs

Derived

Rgles :
Ne jamais appeler une fonction virtuelle dans un constructeur. Une fonction virtuelle ne peut pas etre inline Toujours utiliser des pointeurs / rfrences pour utiliser le polymorphisme.

Objets virtuels purs


Une classe de base peut dfinir des fonctions sans les implanter. Elle force ainsi limplantation dans ses classes drives.
class Vehicle { file.h public : virtual ~Vehicle(); virtual float power() const = 0; protected : Vehicle(); };

Philosophie de lHritage
Hritage public est un En dautres termes: Ce qui sapplique a une classe de base sapplique a ses classes drives.
Question: une classe Carre peut-elle deriver dune classe Rectangle ? Reponse : non ! Ce qui est vrai pour un rectangle n est pas vrai pour un carre.

Philosophie de lHritage
Hritage de l Hritage de l interface implantation Fonction non virtuelle Fonction virtuelle Fonction virtuelle pure Obligatoire Obligatoire

Obligatoire

Obligatoire

Par dfaut, possibilit de redfinir Non, redfinir

Le C++
Historique Du C au C++ Les Classes Lhritage Programmation gnrique

Paramtrer des classes


Cas dune liste chane: les objets de la liste peuvent etre de type diffrent. (void*)
template<class T> class List { public : List( int nb_items ); ~List(); file.h

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

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

file.h

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

Les templates
Le code template nest compil que lors de linstanciation. On peut utiliser typename (ANSI), class ou int comme arguments templates. On peut imposer des fonctions aux arguments templates.

Exemple
template <class T> class List { // };
/** * Sorts a List of objects of type T. * T must provide operators < */

file.h

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

Programmation Gnrique
Ide: Remplacer les fonctions virtuelles par des spcifications darguments templates

Conclusions
Quelques heures pour apprendre le C++ Cest peu !!!
Gestion des exceptions Amiti entre objets Standard Template Library ANSI C++ Pratique

Rfrences
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.

Vous aimerez peut-être aussi