2. Cours semaine 2 jour 2 Cours C++
Plan du jour
Héritage (simple) et composition
Polymorphisme, fonctions virtuelles
Les frameworks, MFC ; Présentation des
templates
2
3. Cours semaine 2 jour 2 Cours C++
Composition
L’avantage des langages orientés objet sur
les autres langages plus anciens est la
réutilisation du code :
La réutilisation du code est possible grâce à
l’héritage : le code réutilisé est défini dans un
seul endroit
Dans les langages procéduraux et les ADT, la
réutilisation se fait par copier/coller puis
modification
3
4. Cours semaine 2 jour 2 Cours C++
Composition (2)
L’héritage n’est pas l’unique mécanisme de
définition des objets !
Comme nous l’avons déjà vu avec UML, il
existe deux mécanismes
« est-un » (is-a en anglais)
« a-un » (has-a en anglais)
4
5. Cours semaine 2 jour 2 Cours C++
Composition (3)
« est-un » marque l’héritage proprement dit
Un cheval est un mammifère
Un dauphin est un mammifère
… et mammifère a de forte chance d’être la
classe mère de cheval et de dauphin
« a-un » marque la composition
Un cheval a des pattes
Un dauphin a des nageoires
5
6. Cours semaine 2 jour 2 Cours C++
Composition (4)
Attention au langage quotidien !
Ce n’est pas parce que vous utilisez une
expression, dans votre langage habituel ou
technique quotidien, que cette expression
représente fidèlement un concept objet !
Il est par exemple permis de dire qu’une voiture
est un véhicule motorisé, pourtant, il s’agit d’un
véhicule avec un moteur !!!!
Les limites de la représentation objet sont dans
votre vocabulaire quotidien !
6
7. Cours semaine 2 jour 2 Cours C++
Composition (5)
La composition est le mécanisme le plus
simple d’emploi
Nous l’utilisons depuis le début en définissant
des classes contenant des variables de type de
base : il s’agit déjà de composition
Il est bien sûr permis d’utiliser des classes
plutôt que des types de base dans la
composition des objets
7
8. Cours semaine 2 jour 2 Cours C++
Composition (6)
class X { // une première classe
int i;
public: X() : i( 0 ) {}
X( int ii ) : i( ii ) {};
void set( int ii ) { i = ii; }
int get() { return i; }
};
class Y { // une deuxième classe
int i;
public: Y() : i( 0 ) {}
Y( int ii ) : i( ii ) {}
void setInt( int ii ) { i = ii; }
int getInt() { return i; }
int mul( int ii ) { return i * ii; }
};
8
9. Cours semaine 2 jour 2 Cours C++
Composition (7)
class Z { // une troisième classe
int i;
X x;
public: Z() : i( 0 ) {}
void setInt( int ii ) { i = ii; }
int getInt() { return i; }
void setX( X xx ) { x = xx; }
int getX() { return x; }
Y transform( int ii ) { return Y( ( i + ii ) * x.get() ); }
};
9
10. Cours semaine 2 jour 2 Cours C++
Composition (8)
Avec le mécanisme de la composition, on
effectue de la réutilisation de code par appel
du code des attributs qui constituent la
classe
Cependant, il est possible de considérer
cette réutilisation comme équivalente à celle
possible dans les langages procéduraux où
les appels de fonctions peuvent être
imbriqués
10
11. Cours semaine 2 jour 2 Cours C++
Composition (9)
Rappel : en UML, il existe trois types de
composition, plus ou moins contraignantes
Association
Aggrégation
Composition
C++ ne fait pas la différence entre ces trois
types de composition, c’est au programmeur
de faire la différence par le codage
11
12. Cours semaine 2 jour 2 Cours C++
Héritage
Un autre mécanisme permet de
véritablement mettre en place la
réutilisation du code par l’héritage en
précisant qu’une classe est la fille d’une
autre
Cela se précise juste après la définition du nom
de la classe en cours de définition
12
13. Cours semaine 2 jour 2 Cours C++
Héritage (2)
class X {
int i;
public: X() : i( 1 ) {}
X( int ii ) : i( ii ) {};
void set( int ii ) { i = ii; }
int get() { return i; }
};
class Y : public X { // la classe Y hérite de la classe X
int i; // pas le même i !
public: Y() : i( 0 ) {}
Y( int ii ) : i( ii ) {}
void setInt( int ii ) {
i = ii;
X::set( ii ); // accès au i de X, :: et pas . !
}
int getInt() { return i; }
int mul( int ii ) { return i * ii; }
};
13
15. Cours semaine 2 jour 2 Cours C++
Héritage (4)
Une sous classe hérite de tous les attributs
et de toutes les méthodes publiques ou
protégées de la classe mère
Lorsque des conflits de noms se produisent,
l’utilisation de l’espace de nommage permet de
résoudre les problèmes
L’héritage n’est pas statique, les
initialisations des attributs de la (des)
classe(s) mère sont effectuées également
15
16. Cours semaine 2 jour 2 Cours C++
Héritage (5)
Les initialisations par défaut de la classe
mère peuvent être modifiées par la classe
fille lors de l’appel du constructeur de la
classe fille qui appellera alors le
constructeur de la classe mère
Dans ce cas, l’initialisation de la classe mère
apparaît au même titre que celui de la classe
fille
16
17. Cours semaine 2 jour 2 Cours C++
Héritage (6)
class X {
int i;
public: X() : i( 1 ) {}
X( int ii ) : i( ii ) {};
void set( int ii ) { i = ii; }
int get() { return i; }
};
class Y : public X {
int i;
public: Y() : X( 10 ), i( 0 ) {} // modification appel constructeur X()
Y( int ii ) : i( ii ) {}
void setInt( int ii ) {
i = ii;
X::set( ii );
}
int getInt() { return i; }
int mul( int ii ) { return i * ii; }
};
17
18. Cours semaine 2 jour 2 Cours C++
Héritage (7)
In fine, il est possible de mélanger les
mécanismes de composition et d’héritage
Plusieurs objets sont instantiés à la création
Ils seront tous détruits lorsque le programme
terminera son exécution ou lorsque l’objet
considéré ne sera plus utilisé
L’appel des constructeurs peut être explicite
L’appel de tous les destructeurs sera
automatique
18
19. Cours semaine 2 jour 2 Cours C++
Héritage (8)
#include <iostream>
using namespace std;
class A {
int i;
public:
A( int ii ) : i( ii ) { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
void f() const { cout << "A::f()" << endl; }
};
class B {
int i;
public:
B( int ii ) : i( ii ) { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
void f() const { cout << "B::f()" << endl; }
};
19
20. Cours semaine 2 jour 2 Cours C++
Héritage (9)
class C : public B {
A a;
public:
C(int ii) : a( ii ), B( ii ) { cout << "C()" << endl; }
~C() { cout << "~C()" << endl; }
void f() const {
cout << "C::f()" << endl;
a.f();
B::f();
}
};
void main() {
C c( 24 ); // 1) constructeurS
c.f(); // 2) fonctionS
} // 3) destructeurS
20
21. Cours semaine 2 jour 2 Cours C++
Héritage (10)
B() // 1, avant A !
A() // 1
C() // 1
C::f() // 2
A::f() // 2
B::f() // 2
~C() // 3
~A() // 3
~B() // 3
21
22. Cours semaine 2 jour 2 Cours C++
Héritage (11)
De la trace d’exécution précédente, il faut déduire
que les classes héritées sont initialisées avant les
classes qui sont data members
L’initialisation se fait toujours de la classe la plus
haute dans la hiérarchie qui est initialisée une fois
que tous ses objets data member sont initialisés
Le même principe est appliqué tout au long du
chemin d’héritage, qu’une initialisation explicite
ait été fournie ou pas
22
23. Cours semaine 2 jour 2 Cours C++
Héritage (12)
Dans la classe C précédente, il existe une fonction
f qui a la même signature que la fonction f de la
classe B
Il s’agit d’une redéfinition de la fonction f car f existait
déjà
Le mécanisme est le même que pour les variables…
La fonction f de B reste cependant invocable grâce
à l’utilisation des espaces de nommage
B::f() dans notre exemple
23
24. Cours semaine 2 jour 2 Cours C++
Héritage (13)
Attention, certaines choses ne s’héritent pas
Les constructeurs et destructeurs ne s’héritent
pas car ils sont appelés pour créer les différents
constituants de l’objet
L’opérateur = ne s’hérite pas non plus
Il s’agit d’une sorte de constructeur déguisé qui est
spécifique à la classe
Le compilateur en définit une version par défaut
24
25. Cours semaine 2 jour 2 Cours C++
Héritage (14)
Il est possible d’hériter des attributs et des
méthodes statiques dans une classe fille
Cependant, la redéfinition d’un attribut ou
d’une méthode statique dans une classe fille
va limiter la visibilité sur toutes les autres
méthodes héritées
Cela permet d’éviter quelques effets de bord
indésirables !
25
26. Cours semaine 2 jour 2 Cours C++
Héritage (15)
Différents niveaux de protection des accès
sont offerts aux constituants d’une classe
Les constituants peuvent être privés et ne seront
pas accédés par les autres classes, qu’elles
soient filles ou non
Les constituants peuvent être protégés et ne
seront accessibles que par les classes filles
Les constituants peuvent être public et seront
accessibles à tous
26
27. Cours semaine 2 jour 2 Cours C++
Héritage (16)
L’héritage peut lui aussi se faire de
plusieurs manières, en utilisant les même
mots clé
class B : A OU class B : private A
class B : protected A
class B : public A
Ces trois types d’héritage permettent des
accès différents à la classe mère
27
28. Cours semaine 2 jour 2 Cours C++
Héritage (17)
L’héritage privé permet de dire que l’on
hérite de la classe mère mais l’ensemble des
données et traitements, bien que présents,
ne pourront pas être utilisés sur une instance
de la classe fille. De plus il sera impossible
de réaliser un downcasting en suivant le
chemin d’un héritage privé
Utilité : ??
28
29. Cours semaine 2 jour 2 Cours C++
Héritage (18)
L’héritage protégé permet de faire varier
l’aspect de la classe aux utilisateurs
extérieurs. Un héritage protégé permet de
donner l’impression que la classe fille peut
se comporter comme sa mère sans pour
autant en être officiellement la fille
Utilité : TRÈS rare !
29
30. Cours semaine 2 jour 2 Cours C++
Héritage (19)
L’héritage public permet de conserver les
constituants (variables et méthodes
protégées et publiques) de la classe mère et
de laisser les sous-classes de la classe
courante en hériter également
C’est l’héritage d’UML
C’est aussi le plus courant
Moralité : n’oubliez pas le « public »
30
31. Cours semaine 2 jour 2 Cours C++
Héritage (20)
#include <iostream>
using namespace std;
class A {
private: int priv;
protected: int i;
public: void setI( int ii ) { i = ii; }
};
class B : public A {
public: int j;
void setJ( int jj ) { j = jj; }
};
void main() {
B b;
b.setI( 1 );
b.setJ( 2 );
//cout << b.i << endl;
cout << b.j << endl;
} 31
32. Cours semaine 2 jour 2 Cours C++
Héritage (21)
Note : le copy-constructeur est hérité de
manière spéciale
Le copy-constructor par défaut d’une classe
fille correspond à l’ « addition » des copy-
constructor des classes mère auquels
s’additionne le copy-constructor de la classe
courante, pour la duplication des data members
définis explicitement dans la classe fille
Rappel : les data members peuvent être, eux
aussi, des objets…
32
33. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles
Nous avons vu hier qu’il était possible,
grâce aux langages orientés objets, de faire
du dynamic binding et de décider au dernier
moment quelle méthode appeler
Ce mécanisme est accessible en C++ grâce
au mot clé virtual qui signale au
compilateur que la fonction mentionnée doit
pouvoir effectuer le dynamic binding
33
34. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (2)
Nous avons vu dans les exemples
précédents qu’il était possible de redéfinir
(redefinition), dans une classe fille, une
méthode ayant la même signature qu’une
autre définie dans la classe mère
Pourtant, grâce aux notions d’espace de
nommage, les deux restent accessibles !
Il ne s’agissait donc pas de dynamic binding !
34
35. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (3)
En fait, le compilateur crée typiquement un
tableau des fonctions virtuelles d’une classe
qui permet par la suite de véritablement
mettre en œuvre le polymorphisme
Ceci permet de pouvoir compiler les classes
contenant des fonctions virtuelles sans que
le binding soit réalisé
Pour illustration :
35
36. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (4)
#include <iostream>
using namespace std;
class PasDeVirtual {
int a;
public: void x() {}
int i() { return 1; }
};
class UneVirtual {
int a;
public: virtual void x() {}
int i() { return 1; }
};
class DeuxVirtual {
int a;
public: virtual void x() {}
virtual int i() { return 1; }
};
36
37. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (5)
void main() {
cout << "* Pour comparaison" << endl;
cout << "int : " << sizeof( int ) << endl;
cout << "void* : " << sizeof( void* ) << endl;
cout << "* les trois fonctions" << endl;
cout << "PasDeVirtual: " << sizeof( PasDeVirtual ) << endl;
cout << "UneVirtual : " << sizeof( UneVirtual ) << endl;
cout << "DeuxVirtual : " << sizeof( DeuxVirtual ) << endl;
}
* Pour comparaison
int : 4 // la taille d’un mot 32 bits
void* : 4
* les trois fonctions
PasDeVirtual: 4
UneVirtual : 8 // mécanisme de dynamique binding
DeuxVirtual : 8 // mécanisme de dynamique binding
Résultat :
37
38. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (6)
Dans l’exemple précédent, certaines
fonctions virtuelles contiennent une
implémentation
Cas pour la fonction i() dans la classe
DeuxVirtual
Ceci est autorisé car il est possible qu’une
partie du traitement doivent être défini au
niveau de la classe mère
38
39. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (7)
Mais cela permet aussi de créer de
véritables instances de la classe mère, ce qui
n’est peut-être pas voulu
Aussi, il existe un moyen de définir des
classes « abstraites » qui ne pourront pas
avoir d’instances à l’aide des pure virtual
functions
Dans ce cas, on ne donne pas le corps de la
méthode virtuelle mais juste sa signature
39
40. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (8)
Avec des pure virtual functions, il devient
impossible de créer une instance d’une
classe en contenant
40
41. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (9)
#include <iostream>
#include <string>
using namespace std;
class Mere {
public:
virtual int f() {
cout << "Mere::f()" << endl;
return 1;
}
virtual void f( string s ) {
cout << "Mere::f( " << s << " )" << endl;
}
virtual void g() {}
};
class Fille1 : public Mere {
public:
void g() {}
}; 41
42. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (10)
class Fille2 : public Mere {
public:
int f() {
cout << "Fille2::f()" << endl;
return 2;
}
};
class Fille3 : public Mere {
public:
int f() {
cout << "Fille3::f()" << endl;
return 2;
}
int f( int ) {
cout << "Fille3::f( int )" << endl;
return 3;
}
}; 42
43. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (11)
void main() {
string s( "coucou" );
Fille1 f1;
int x = f1.f();
f1.f( s );
Fille2 f2;
x = f2.f();
Fille3 f3;
x = f3.f( 1 );
Mere& m = f3;
m.f();
m.f( s );
}
43
44. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (12)
Mere::f()
Mere::f( coucou )
Fille2::f()
Fille3::f( int )
Fille3::f()
Mere::f( coucou )
44
45. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (13)
Il est également possible de traiter les
constructeurs et les destructeurs au travers
de fonctions virtuelles
Dans ce cas, l’utilisation des virtual permet
d’effectuer un ensemble complet d’opérations
même après avoir réalisé un upcasting
L’upcasting se produit normalement avec perte
d’information sauf si l’on emploie virtual
45
46. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (14)
#include <iostream>
using namespace std;
class Mere1 {
public:
~Mere1() { cout << "~Mere1()" << endl; }
};
class Fille1 : public Mere1 {
public:
~Fille1() { cout << "~Fille1()" << endl; }
};
class Mere2 {
public:
virtual ~Mere2() { cout << "~Mere2()" << endl; }
};
class Fille2 : public Mere2 {
public:
~Fille2() { cout << "~Fille2()" << endl; }
};
46
47. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (15)
Avec un upcasting sans virtual, on perd de
l’information avant même le destructeur !
~Mere1()
~Fille2()
~Mere2()
47
48. Cours semaine 2 jour 2 Cours C++
Fonctions virtuelles (16)
Les fonctions virtuelles sont à la base du
polymorphisme à toutes les étapes de la vie d’un
objet
Elles correspondent au mécanisme de base
permettant de mettre le polymorphisme en œuvre
Elles sont donc nécessaires dans les langages
orientés objet mais consomment
du temps de traitement
de l’espace mémoire
48
49. Cours semaine 2 jour 2 Cours C++
Généricité
Il est intéressant de pouvoir utiliser
l’héritage pour fournir la possibilité de
réutiliser du code
Il existe cependant certains cas où l’héritage
est tout de même une manière limitée de
réutiliser le code déjà écrit
Il est alors possible d’utiliser, en C++, la
programmation générique, qui n’a rien à
voir avec la programmation orientée objet !
49
50. Cours semaine 2 jour 2 Cours C++
Généricité (2)
Supposons que nous ayons une classe très
générale, comme une pile ou une file
Cette structure de donnée effectue des
opérations qui sont indépendantes du type des
objets stockés (tels que les types de base
comme int ou les classes comme Integer)
Il serait bon de pouvoir noter ces types de
manière paramétrable
50
51. Cours semaine 2 jour 2 Cours C++
Généricité (3)
Cela existe en C++, il s’agit des templates
Un template est une classe qui prend
comme paramètre de construction un type,
en plus des éventuels paramètres passés aux
constructeurs
Ce type donné au template n’est pas un
argument comme les autres !
51
52. Cours semaine 2 jour 2 Cours C++
Généricité (4)
#include <iostream>
using namespace std;
template< class T >
class Tableau {
enum { size = 100 };
T A[ size ];
public:
T& operator[]( int idx )
{
return A[ idx ];
}
};
52
53. Cours semaine 2 jour 2 Cours C++
Généricité (5)
void main() {
Tableau<int> ia;
Tableau<float> fa;
for( int i = 0; i < 20; i++ )
{
ia[ i ] = i * i;
fa[ i ] = float( i ) * 2.718;
}
for(int j = 0; j < 20; j++)
{
cout << j << ":t";
cout << ia[ j ]<< ",t";
cout << fa[ j ] << endl;
}
}
53
54. Cours semaine 2 jour 2 Cours C++
Généricité (6)
Le type générique du template n’est pas
l’unique argument qu’il est possible de
donné
Il est possible de donner d’autres paramètres
#include <iostream>
using namespace std;
template< class T, int size = 100 >
class Tableau {
T A[ size ];
…
};
54
55. Cours semaine 2 jour 2 Cours C++
Généricité (7)
Les templates permettent de créer des
définitions de classe qui peuvent être
largement utilisées
Il s’agit de sortes de containers qui ne se
préoccupent pas du contenu des « cases »
mais juste des cases elles-mêmes
55
56. Cours semaine 2 jour 2 Cours C++
Généricité (8)
De plus, comme nous sommes dans un
monde orienté objet, où l’encapsulation fait
force de loi, il est possible d’envisager de
définir des fonctions génériques
encapsulées dans les classes génériques
En passant des (sous) fonctions typées à ces
fonctions génériques, il devient possible de
réaliser des actions
56
57. Cours semaine 2 jour 2 Cours C++
Généricité (9)
Les fonctions génériques peuvent par
exemple être des fonctions de support à une
itération permettant de déterminer une
condition sur les éléments du type
générique
La fonction spécifique effectue un test sur le
bon type
Ces fonctions servent de base à la mise en place
d’itérateurs
57
59. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft
Dans l’environnement Microsoft, par
l’intermédiaire de Visual Studio, le
programmeur est guidé dans toutes ses
démarches par les wizards (assistants)
Jusqu’à présent, nous avons pris nos libertés
et écrit des programmes pouvant être
compilés aussi bien sur Windows qu’UNIX
mais il n’y avait aucun système multifenêtré
59
60. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (2)
Les Microsoft Foundation Classes
fournissent un ensemble de classes de base
utilisables sur la plate-forme Windows
Comme leur nom l’indique, elles ont été
développées par Microsoft
Il en existe des portages, généralement partiels,
sur d’autres systèmes d’exploitation tels
qu’Unix, dont Linux
60
61. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (3)
Les MFC fournissent une aide non
négligeable à la programmation sous
Windows
Elles regroupent un ensemble de points d’entrée
dans le système Windows
Elles permettent ainsi de rapidement
développer des applications, avec l’aide des
assistants (les fameux wizards)
61
62. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (4)
Quelque soit la technologie utilisée lors du
développement d’application Windows avec
Visual C++, le code généré
automatiquement ne doit JAMAIS être
modifié
Vous pouvez le faire suffisament bien pour ne
pas avoir de blue screens tout de suite
À la prochaine version de Windows, vous aurez
des blue screens…
62
67. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (9)
Un programme Windows (32 bits) possède
deux éléments essentiels :
WinMain, qui est unique pour chaque
programme, cela définit le point d’entrée de
l’application
WndProc, qui doit être instancié autant de fois
qu’il y a de fenêtres
Ces éléments sont créés par MFC
67
68. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (10)
Le WinMain aura en charge le traitement
des messages et leur reroutage vers la bonne
fenêtre WndProc, dans le cas où il y en a
plusieurs
WndProc, à chaque réception de message,
regarde sa table des gestionnaires de
messages (message handlers) pour savoir
s’il en existe un bon
68
69. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (11)
Le but d’un programmeur Windows est
normalement d’écrire ces message handlers
de manière à enrichir le comportement de
l’application
Normalement, Microsoft s’occupe du reste !
69
70. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (12)
70
71. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (13)
71
72. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (14)
72
73. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (15)
#include <afxwin.h>
// la fenetre herite de CFrameWnd
class CMaFenetre : public CFrameWnd
{
public:
CMaFenetre( );
DECLARE_MESSAGE_MAP( )
};
// constructeur de la fenetre
CMaFenetre::CMaFenetre( )
{
Create( 0, "Premiere appli MFC avec fenetre P&T" );
}
// l'application herite de CWinApp
class CMonAppli : public CWinApp
{
public:
virtual BOOL InitInstance( );
}; 73
74. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (16)
// la methode InitInstance() de l'application
// c.a.d le constructeur version M$
BOOL CMonAppli::InitInstance()
{
m_pMainWnd = new CMaFenetre( );
m_pMainWnd->ShowWindow( m_nCmdShow );
m_pMainWnd->UpdateWindow();
return TRUE;
}
// la table des messages de l'application
BEGIN_MESSAGE_MAP( CMaFenetre, CFrameWnd )
// tous les messages traites par CMaFenetre
// doivent etre listees ici
END_MESSAGE_MAP()
// declaration d'une instance de l'application
// utilisable par WinMain
CMonAppli app;
74
75. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (17)
75
76. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (18)
76
77. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (19)
WinMain exécute le code CMonAppli app :
création d’un objet app possédant les
variables et fonctions de CWinApp
nécessaires au lancement, à l’exécution et à
la fermeture du programme
WinMain fait alors appel à InitInstance()
pour créer un CMaFenetre qui sera la
fenêtre principale (m_pMainWnd du
programme)
77
78. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (20)
CMaFenetre appelle la fonction Create() qui
crée une instance de fenêtre SANS
l’afficher à l’écran
L’affichage est réalisé par ShowWindow
WinMain appelle enfin Run() pour le
dispatching des messages (mais nous n’en
avons défini aucun…)
78
79. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (21)
Cette application ne comporte aucun
message handler
Donc elle ne fait rien
Cette application prend les valeurs par
défaut du système, il est possible d’en
changer certaines
79
80. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (22)
// constructeur de la fenetre
CMaFenetre::CMaFenetre( )
{
//Create( 0, "Premiere appli MFC avec fenetre P&T" );
RECT x;
x.top = 30;
x.left = 30;
x.bottom = 300;
x.right = 300;
Create( NULL, "P&T bis", WS_OVERLAPPEDWINDOW, x );
}
80
81. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (23)
81
82. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (24)
Cette solution est explicative mais lourde…
Microsoft fournit des wizard pour faire ce
genre d’opérations
Les assistants ont tendance à cacher beaucoup
de choses…
82
83. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (25)
83
84. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (26)
84
85. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (27)
85
86. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (28)
86
87. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (29)
87
88. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (30)
88
89. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (31)
89
90. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (32)
90
91. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (33)
91
92. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (34)
Le fichier C++ principal commence, comme
par hasard, avec la message map qui permet
d’associer des handlers aux messages qui
pourraient être dispatchés vers la fenêtre
En regardant le reste du code, on reconnaît
une version anméliorée du code source
présenté avant.
92
93. Cours semaine 2 jour 2 Cours C++
Un peu de Microsoft (35)
Microsoft simplifie le développement à l’aide des
assistants et grâce à la définition de libraires,
frameworks et templates tels que ceux qu’il est
possible de trouver dans MFC
Si MFC est justifiable pour la gestion des fenêtres
sous Windows, l’utilisation de librairies
algorithmiques plus standardisées peut être
intéressant pour le cœur du programme
93