0% ont trouvé ce document utile (0 vote)
295 vues32 pages

Interfaces Graphiques, Complement C++

Le document décrit les concepts de base de la programmation orientée objet en C++, notamment l'agrégation, l'héritage, la compilation séparée et les espaces de noms. Il fournit des exemples de code pour illustrer ces concepts.

Transféré par

nour alrafee
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
295 vues32 pages

Interfaces Graphiques, Complement C++

Le document décrit les concepts de base de la programmation orientée objet en C++, notamment l'agrégation, l'héritage, la compilation séparée et les espaces de noms. Il fournit des exemples de code pour illustrer ces concepts.

Transféré par

nour alrafee
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
Vous êtes sur la page 1/ 32

1 Compléments C++

– Agrégation
– Utilisation de l’héritage
– Compilation séparée
– Espaces de noms
– Vecteurs

1. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


2 Agrégation : relation « A-UN »
2.1 Objets contenant d’autres objets
– On a des classes pour représenter une chaîne de caractères et une date :

class string { class date {


public: public:
string(const char* s); date(int day, int month, int year);
string(const string& s); date(const date& d);
... ...
private: private:
char* d_data; int d_day, d_month, d_year;
int d_size; };
};

2. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– On veut représenter un client : il a un nom et une date de naissance

class client
{
public :
client(const string& name, const date& birthdate);
client(const char* name, int birthday,int birthmonth,int birthyear);
private :
string d_name;
date d_birthdate;
};

– Pour construire un client, il faut d’abord construire d_name, sa partie


string et d_birthdate sa partie date
⇒ on appelle les constructeurs des objets composant un autre objet dans la
liste d’initialisation de son constructeur :

3. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


client::client(const string& name, const date& birthdate) :
d_name{name}, d_birthdate{birthdate}
{
//additional stuff
}

client::client(const char* name,


int birthday, int birthmonth, int birthyear) :
d_name{name}, d_birthdate{birthday,birthmonth,birthyear}
{
//additional stuff
}

– Une fois dans le corps du constructeur, les champs sont déjà construits.

4. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


2.2 Création/destruction des objets composites
Création d’un objet :

1. allocation de la mémoire physique qu’il occupe ;


2. appel des constructeurs des objets qui le composent dans l’ordre de déc-
laration de ces objets : constructeurs de la liste d’initialisation, par défaut
sinon ;
3. exécution du corps de son constructeur.

Destruction d’un objet, en sens inverse :

1. exécution du corps de son destructeur ;


2. appel des destructeurs des objets qui le composent dans l’ordre inverse de
déclaration de ces objets ;
3. libération de la mémoire physique qu’il occupe.

5. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


2.3 Copie des objets composites
Constructeur de recopie
– Le constructeur de recopie généré par défaut crée et initialise les champs
d’un objet un à un par appel à leur constructeur de recopie
⇒ pas besoin de le redéfinir si les constructeurs de recopie des champs sont
corrects

class toto {
A d_a;
B d_b;
C d_c;
};

//generated copy constructor

toto::toto(const toto& t) : d_a{t.d_a}, d_b{t.d_b}, d_c{t.d_c}


{}
Opérateur d’affectation
– L’opérateur d’affectation généré par défaut fait une copie champ à champ
de l’objet, les champs étant copiés avec leur opérateur d’affectation
⇒ pas besoin de le redéfinir si les opérateurs d’affectation des champs sont
corrects

//generated affectation operator

toto& toto::operator=(const toto& t)


{
d_a = t.d_a; //d_a.operator=(t.d_a)
d_b = t.d_b;
d_c = t.d_c;
return *this;
}

7. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


3 Introduction à l’utilisation de l’héritage
– On a besoin de personnaliser une classe :

– en lui ajoutant des nouvelles fonctionnalités,


– mais sans la modifier

→ créer une nouvelle classe dérivée de cette classe (dite classe de base)
– Un objet de la classe dérivée est alors composé d’une partie objet classe de
base
– Le constructeur de la classe dérivée doit appeler celui de la classe de base
– La classe dérivée hérite des méthodes de la classe de base : on peut appeler
les méthodes de la classe de base sur un objet de la classe dérivée
– La classe dérivée est même utilisable partout à la place de la classe de base

8. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– On a une classe point :

class point {
public:
point(double x, double y);
double x() const;
double y() const;
void moveTo(double x, double y);
private:
double d_x, d_y;
};

void utiliserPoint(point& p);

– On veut lui rajouter une étiquette (une chaîne de caractères)


→ créer la classe dérivée pointEtiquete

9. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


class pointEtiquete : public point { //hérite de point
public:
pointEtiquete(double x, double y, const string& etiq);
string etiquette() const;
private:
string d_etiquette;
};

pointEtiquete::pointEtiquete(double x, double y, const string& etiq) :


point{x,y}, //constructeur classe de base
d_etiquette}etiq}
{}

string pointEtiquete::etiquette() const { return d_etiquette; }

– On peut utiliser un pointEtiquete à la place d’un point :


pointEtiquete pe{10,5,"mairie"};
cout<<pe.etiquette()<<" en "<<pe.x()<<", "<<pe.y()<<endl;
utiliserPoint(pe);

10. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


4 Compilation séparée
– Un programme est réparti dans plusieurs fichiers :

– plusieurs personnes travaillent ensembles sur le projet,


– le découpage d’un programme en fichiers aide à exprimer sa structure
logique (pour les programmeurs et le compilateur),
– sans découpage il faudrait tout recompiler au moindre changement.

– Le programme est découpé en plusieurs fichiers source donnés au compi-


lateur qui invoque plusieurs programmes
– Le préprocesseur transforme un fichier source en unité de traduction
– Le compilateur compile une unité de traduction en fichier objet con-
tenant le code objet du fichier source
– L’éditeur de liens rassemble tous les codes objets à l’édition de liens pour
produire le programme exécutable

11. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


4.1 Le C-préprocesseur
– Il est invoqué automatiquement en premier.
– Il fait des transformations de texte à partir du fichier source grâce à des
directives avant de transmettre le résultat au compilateur.

Inclusion de fichiers :

– La directive #include permet d’inclure textuellement le contenu d’un


autre fichier

#include<iostream> //standard C++ header files


#include<time.h> //other system header files
#include"myheader.h" //user header files

12. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


Macros :

– La directive #define permet définir des macros qui définissent des sub-
stitutions automatiques dans le texte :

#define NMAX 10
//NMAX is textually replaced by 10

#define max(a,b) (a>b) ? a : b


//macro with parameters

– Les macros sont dangereuses : pas de vérification de types et effets de bord


⇒ à proscrire !
– Utiliser les constantes et les fonctions en-ligne à la place.

13. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– On peut tester si une macro a déjà été définie ou non avec les directives
#ifdef ... #endif et #ifndef ... #endif
– Un compilateur C++ définit toujours la macro __cplusplus,
– On peut définir une macro dans un fichier puis la tester ailleurs pour savoir
si le fichier a déjà été inclus : permet d’éviter les inclusions multiples

⇒ à utiliser systématiquement pour les fichiers en-tête.

fichier myinclude.h :

#ifndef MYINCLUDE_H
#define MYINCLUDE_H

//contenu du fichier en-tête myinclude.h

#endif

14. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


4.2 Compilation en fichier objet
– Pour pouvoir compiler une unité de traduction en un fichier objet, le com-
pilateur doit connaître :

– les déclarations des fonctions appelées (définitions si en-ligne),


– les définitions des types utilisateurs utilisés ;

– Les définitions des types utilisateurs ne peuvent apparaître qu’une seule


fois dans une unité de traduction ;
– L’unité de traduction doit contenir les définitions de tout ce qui ne peut
être partagé avec d’autres unités.

15. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


4.3 Édition de liens
– L’éditeur de liens regroupe en un seul tout exécutable les codes objets qui
lui sont donnés
– Il remplace les noms des fonctions et des variables (symboles) par leur
adresse mémoire dans le code final
→ les définitions des variables globales et fonctions utilisées doivent figurer
au final une et une seule fois,
– Les définitions des types utilisateurs peuvent apparaître plusieurs fois au
final si c’est de façon identique.

16. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


4.4 Découpage en fichiers
→ On répartit le code dans deux sortes de fichiers :

– les fichiers en-tête :

– ils sont inclus par les autres fichiers pour pouvoir utiliser les types
(classes, . . . ), fonctions . . . , qui y sont déclarés,
– ils doivent être protégés contre les inclusions multiples,

– les fichiers source :

– ils contiennent les définitions,


– ce sont eux qui sont passés au compilateur pour créer les fichiers
objets.

17. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Un fichier en-tête peut contenir :

des inclusions de fichiers en-tête #include<cmath>


des commentaires documentants //author: .....

des définitions de constantes const double PI=3.1415926535;


des définitions d’énumérations enum light { red, yellow, green };

des déclarations de noms class list;


des définitions de types class point {
double x,y;
public:
point(double x,double y);
};

des déclarations de fonctions void print(point );


des définitions de fonctions en-ligne inline double dist(point p)
{ return sqrt(p.x*p.x+p.y*p.y); }

18. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Un fichier source peut contenir :

des inclusions de fichiers en-tête #include"point.h"

les définitions des méthodes void point::moveTo(double x,double y)


{ d_x=x; d_y=y; }

les définitions des fonctions void print(point p)


{ cout<<’(’<<p.x()<<’,’<<p.y()<<’)’; }

19. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


5 Gestion de la compilation séparée : make et
Makefile
– Pour avoir un programme exécutable il faut :

– compiler les fichiers source en fichiers objets :


g++ -c toto.cpp
g++ -c tata.cpp
...
– réunir les fichiers objets à l’édition de liens :
g++ toto.o tata.o ... -o resultat

– Quand des fichiers sont modifiés, il ne faut recompiler que ces fichiers et
ceux qui les incluent
⇒ gestion automatique des dépendances grâce au programme make et à son
fichier de configuration Makefile.

20. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


5.1 Makefile
– Un fichier de configuration Makefile contient des instructions de la forme :

cible : dépendances
<tab>commande à exécuter

– cible : nom d’un fichier à générer


– dépendances : noms des fichiers qui s’ils sont modifiés entraînent la
re-génération de la cible
– commande à exécuter : commande à exécuter pour générer la cible

– Le programme make lit ce fichier Makefile pour déterminer quelles sont


les commandes à exécuter pour générer les fichiers :

– make cible : génère la cible indiquée


– make : génère la première cible du Makefile

21. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Pour générer une cible make :

– génère les dépendances si ce sont des cibles


– re-génère la cible en exécutant la commande si
la cible n’est pas à jour, c.-à-d. si elle n’existe
pas ou est plus vieille qu’une des dépendances.

– Gestion de la compilation séparée :

– compiler les fichiers sources en fichiers objets


– édition de liens pour générer l’exécutable

#génération du programme exécutable


progtest : toto.o tata.o progtest.o
<tab>g++ toto.o tata.o progtest.o -o progtest

#génération des codes objets


progtest.o : progtest.cpp toto.h tata.h
<tab>g++ -c progtest.cpp

toto.o : toto.cpp toto.h


<tab>g++ -c toto.cpp

tata.o : tata.cpp tata.h


<tab>g++ -c tata.cpp

22. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Une cible ne désigne pas forcément un fichier à
créer mais peut désigner seulement des ordres à
effectuer

#faire le nettoyage complet : make clean


clean :
<tab>rm *.o
<tab>rm progtest

– Variables :
on peut définir des variables dans un Makefile
pour simplifier l’écriture ou les changements :

– définition d’une variable : NOMVAR = valeur


– utilisation d’une variable : $(NOMVAR)

#nom du compilateur et options de compilation


CXX = g++
CXXFLAGS = -g -Wall

progtest : toto.o tata.o progtest.o


<tab>$(CXX) toto.o tata.o progtest.o -o progtest

#génération des codes objets


progtest.o : progtest.cpp toto.h tata.h
<tab>$(CXX) $(CXXFLAGS) -c progtest.cpp

toto.o : toto.cpp toto.h


<tab>$(CXX) $(CXXFLAGS) -c toto.cpp

23. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


6 Les espaces de noms
– On veut rassembler dans une même portée de noms
plusieurs composants formant un tout logique
– Pour que les noms de ces composants ne soient
pas en conflits avec ceux d’autres bibliothèques
→ Déclarer des espaces de noms namespace :
namespace myGraphics
{
class window { ... };
int nbOpenWindows;
void error(const char* );
}

namespace myDatastr
{
class vector { ... };
bool is_sorted(const vector& );
void error(const char* );
}

– Un espace de noms introduit une portée


⇒ les composants sont accessibles par leur nom qua-
lifié, c.-à-d. préfixé par nom_du_namespace::
– Les composants de la bibliothèque standard sont
dans l’espace de noms std

24. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


#include<cmath>
#include"myGraphics.h"
#include"myDatastr.h"

int main()
{
myGraphics::window w;
if (!w.open())
{ myGraphics::error("cannot open window"); }

myDatastr::vector v(1000);
for (int i=0; i<1000; ++i) { v[i] = std::sqrt(i); }
if (!myDatastr::is_sorted(v))
{ myDatastr::error("error with is_sorted"); }

return 0;
}

25. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Les définitions des composants sont données à l’intérieur de la définition
d’un espace de noms :
#include"datastr.h"

namespace myDatastr
{
vector::vector(int size)
{ ... }

bool is_sorted(const vector& v)


{ ... }

void error(const char* msg)


{ ... }
}

26. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


On peut rendre des composants directement ac-
cessibles grâce à :
– une déclaration d’utilisation pour un composant ;
– une directive d’utilisation pour tous les composants
d’un espace de nom (déconseillé).

#include"myGraphics.h"
#include"myDatastr.h"

using myDatastr::vector; //using declaration


using namespace myGraphics; //using directive

int main()
{
window w;
if (!w.open())
{ error("cannot open window"); }

vector v(1000);
for (int i=0;i<1000;++i) { v[i]=std::sqrt(i); }
if (!myDatastr::is_sorted(v))
{ myDatastr::error("error with is_sorted"); }
}

27. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


7 Outils de base de la STL : conteneurs
7.1 Principes des conteneurs
– Le type des conteneur est paramétré par le type des éléments qu’il con-
tient : conteneur<typeelem> c;
– Les conteneurs ont une sémantique par valeur : ils copient les éléments
insérés en interne et renvoient des copies des éléments
– Les éléments d’un conteneurs doivent pouvoir

– être copiables grâce au constructeur de recopie,


– être affectables grâce à l’opérateur d’affectation,
– être destructibles grâce à leur destructeur,

– Pour certaines opérations, les éléments doivent avoir un constructeur par


défaut, un opérateur d’égalité ==, être comparables (opérateur <)

28. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


Constructeurs et affectation
ContType c crée un conteneur vide
ContType c(c2) constructeur de recopie
ContType c(n) n éléments construits par défaut
ContType c(n,val) n copies de val
˜ContType() détruit le conteneur et ses éléments
c1=c2 affecte les éléments de c2 à c1
c1.swap(c2) échange les données de c1 et c2

– Les opérations ne sont pas sécurisées : l’utilisateur doit faire attention à la


validité des paramètres.

29. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


Informations et accès aux éléments
c.size() nombre d’éléments
c.empty() est-ce-que le conteneur est vide ?
c.max_size() nombre maximum possible d’éléments
c1==c2 est-ce-que les contenus sont les mêmes ?
c1!=c2 est-ce-que les contenus sont différents ?
c1<c2 est-ce-que c1 est avant c2 (ordre lexicographique)
c.front() premier élément
c.back() dernier élément
c[i] accès non vérifié (vector, indice commence à 0)
c.at(i) accès vérifié (lance l’exception out_of_range)
Insertion/suppression
c.push_back(elem) insère l’élément à la fin
c.pop_back() enlève le dernier élément
c.push_front(elem) insère l’élément au début (list)
c.pop_front() enlève le premier élément (list)
c.clear() Enlève tous les éléments (conteneur vide)

30. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


7.2 Vecteurs
– Pour l’utiliser :

– #include<vector>
– vector<typeelem> v

– Un vecteur représente un tableau dynamique


– Accès aléatoire aux éléments : v[i]
– Pour ajouter ou enlever un élément : le faire à la fin du vecteur avec
push_back (insérer) et pop_back (enlever)
(l’insertion/suppression ailleurs n’est pas performante pour les grands vecteurs).

31. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


Taille et capacité
– La taille (=nombre d’éléments) peut être changée avec resize(n) ou
resize(n,val) (éléments supplémentaires initialisés avec val)
– Un vecteur alloue plus de mémoire que nécessaire
– Capacité : nombre d’éléments que le vecteur peut contenir sans avoir à
faire de ré-allocation (capacity())
– La capacité peut être fixée par l’utilisateur avec reserve()

std::vector<int> v;
v.reserve(80);

ou à la construction (dans ce cas taille=capacité)

std::vector<int> v(80); //initialized with default constructed values

– Pour diminuer la capacité à la taille du vecteur : v.shrink_to_fit()

32. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière

Vous aimerez peut-être aussi