Mon blog anglais - Mes articles et critiques de livres - FAQ C++0x, avec liste des nouveautés - Conseils sur le C++ - La meilleure FAQ du monde - Avant de créer des classes que vous réutiliserez, regardez si ça n'existe pas déjà - Le site du comité de normalisation du C++
Le guide pour bien débuter en C++ - Cours et tutoriels pour apprendre C++
N'est-ce pas déjà trop tard de toute façon, pour appeler une fonction virtuelle?
À moins que cette restriction ne s'applique qu'aux constructeurs et pas au destructeur? Je ne sais jamais...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Non cela ne s'applique qu'aux constructeurs
Penser en C++
Envoyé par Bruce Eckel
Ressources proposées par 3DArchi - Les fonctions virtuelles en C++ - Cours et tutoriels C++ - FAQ C++ - Forum C++.
Oui desole pour l'erreur.
Je voulais bien sur dire que la restriction pour l'appel des fonctions virtuelles ne s'applique qu'aux destructeurs.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Je modifierai le code pour résoudre ce soucis, bien que ça ne soit pas le centre de l'article
Mon blog anglais - Mes articles et critiques de livres - FAQ C++0x, avec liste des nouveautés - Conseils sur le C++ - La meilleure FAQ du monde - Avant de créer des classes que vous réutiliserez, regardez si ça n'existe pas déjà - Le site du comité de normalisation du C++
Le guide pour bien débuter en C++ - Cours et tutoriels pour apprendre C++
Oui perdu !!!!
Mais j'aurais appris qqchose !!!
Désolé de faire un petit remontage de post, mais j'aimerais répondre à l'un des interrogations de escafr, vu qu'il n'y a pas eu de réponse à priori...
Comme ça:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 #include <cstdlib> #include <iostream> struct NonClickable; struct Clickable { Clickable() { } Clickable( const NonClickable& ) { } void tell() { std::cout << "Clickable policy" << std::endl; } void click() { std::cout << "Clickable::clicked()" << std::endl; } }; struct NonClickable { NonClickable() { } NonClickable( const Clickable& ) { } void tell() { std::cout << "Nonclickable policy" << std::endl; } // pas de click(); }; template < class ClickPolicy > class Widget : public ClickPolicy { public: Widget(int id) : id_(id) { ClickPolicy::tell(); } template < class OtherClickPolicy > Widget( const Widget< OtherClickPolicy >& o ) : ClickPolicy( o ), id_( o.id_ ) { ClickPolicy::tell(); } int id_; }; int main( int argc, char* argv[] ) { Widget<Clickable> clickableWidget(1); clickableWidget.click(); Widget<NonClickable> nonClickableWidget( clickableWidget ); // nonClickableWidget.click(); compilera pas. // et l'inverse Widget< Clickable > clickableWidgetAgain( nonClickableWidget ); clickableWidgetAgain.click(); return 0; }En réalité, tu ne dois modifier QUE ta classe Widget, ce qui est en fait quelque chose de naturel, vu que c'est l'hôte de la politique que tu veux ajouter.Envoyé par escafr
Rien ne t'empêche de définir des politiques par défaut pour ta classe hôte, en mettant en premier ceux qui sont le plus modifiés. Les nouvelles politiques arrivant naturellement sur les dernières places, et possèdant leur comportement par défaut (quitte à ce que ça soit: "ne rien faire"), ça n'interfèrera pas avec le code existant.
Le nouveau code viendra s'installer naturellement, sans intérférer ou modifier le code existant, ce qui est ce qu'on recherche.
Exemple:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 struct RectangleDraw { void tell() { std::cout << "RectangleDraw policy" << std::endl; } void draw() { std::cout << " _________ " << std::endl; std::cout << "| |" << std::endl; std::cout << "|_________|" << std::endl; } }; struct SquareDraw { void tell() { std::cout << "SquareDraw policy" << std::endl; } void draw() { std::cout << " _____ " << std::endl; std::cout << "| |" << std::endl; std::cout << "| |" << std::endl; std::cout << "|_____|" << std::endl; } }; struct NoDraw { void tell() { std::cout << "NoDraw policy" << std::endl; } }; template < class ClickPolicy = NonClickable, class DrawingPolicy = NoDraw > class Widget : public ClickPolicy, public DrawingPolicy { public: Widget(int id) : id_(id) { policies_tell(); } template < class OtherClickPolicy, class OtherDrawPolicy > Widget( const Widget< OtherClickPolicy, OtherDrawPolicy >& o ) : ClickPolicy( o ), id_( o.id_ ) { policies_tell(); } void policies_tell() { DrawingPolicy::tell(); ClickPolicy::tell(); } int id_; }; int main( int argc, char* argv[] ) { Widget<> wdg(1); // wdg.click() ne compilera pas // wdg.draw() compilera pas // nouveau widget Widget< Clickable, RectangleDraw > crWdg(2); crWdg.click(); crWdg.draw(); return 0; }En réalité, c'est justement l'inverse de l'effet recherché. Préfères-tu écrire une hiérarchie de N^2 classes à multiples héritages ou N classes sans redondance ?Envoyé par escafr
L'héritage pure/multiple, dans ce cas-ci, va nous emmener dans pire que ce qu'on a: au lieu d'avoir un typage fort, on va quasiment pas en avoir, ou du moins pas de controle sur ce dernier.
Je préfère avoir des widgets de type différents dont les types souches sont génériques, c'est à dire Q< T, U, V, W > plutôt que QTUVW, QTUWV, QUTVW, QTUVW, pour ensuite m'amuser à upcaster tout le bordel et essayer de s'y retrouver...
Quant à l'héritage par interface unique, oui, mais tu dois alors souvent trop charger tes interfaces, ce qui est un autre problème en soi.
Ah oui j'avais zappé les questions désolé
Sinon, pour appuyer ce que dis Julien, je rajouterais que si tu as une classe Widget paramétrée par 4 politiques. Si la première a 3 implémentations, la deuxième 4, la troisième 2, et la quatrième 5, ça te fait 3*4*2*5 classes à implémenter si tu veux faire l'équivalent qu'avec l'héritage. C'est à dire 120 classes. Plutôt que justement 3+4+2+5 = 14 classes, qui ne seront que des petits bouts de classe en fait !
Entre 120 et 14, le choix pour moi est vite fait, et le sera probablement également pour un chef de projet correct
Mon blog anglais - Mes articles et critiques de livres - FAQ C++0x, avec liste des nouveautés - Conseils sur le C++ - La meilleure FAQ du monde - Avant de créer des classes que vous réutiliserez, regardez si ça n'existe pas déjà - Le site du comité de normalisation du C++
Le guide pour bien débuter en C++ - Cours et tutoriels pour apprendre C++
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager