Upload
stephane-charlet
View
108
Download
3
Embed Size (px)
Citation preview
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.